@vladimirven/openswe 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +203 -0
- package/CLAUDE.md +203 -0
- package/README.md +166 -0
- package/bun.lock +447 -0
- package/bunfig.toml +4 -0
- package/package.json +42 -0
- package/src/app.tsx +84 -0
- package/src/components/App.tsx +526 -0
- package/src/components/ConfirmDialog.tsx +88 -0
- package/src/components/Footer.tsx +50 -0
- package/src/components/HelpModal.tsx +136 -0
- package/src/components/IssueSelectorModal.tsx +701 -0
- package/src/components/ManualSessionModal.tsx +191 -0
- package/src/components/PhaseProgress.tsx +45 -0
- package/src/components/Preview.tsx +249 -0
- package/src/components/ProviderSwitcherModal.tsx +156 -0
- package/src/components/ScrollableText.tsx +120 -0
- package/src/components/SessionCard.tsx +60 -0
- package/src/components/SessionList.tsx +79 -0
- package/src/components/SessionTerminal.tsx +89 -0
- package/src/components/StatusBar.tsx +84 -0
- package/src/components/ThemeSwitcherModal.tsx +237 -0
- package/src/components/index.ts +58 -0
- package/src/components/session-utils.ts +337 -0
- package/src/components/theme.ts +206 -0
- package/src/components/types.ts +215 -0
- package/src/config/defaults.ts +44 -0
- package/src/config/env.ts +67 -0
- package/src/config/global.ts +252 -0
- package/src/config/index.ts +171 -0
- package/src/config/types.ts +131 -0
- package/src/core/.gitkeep +0 -0
- package/src/core/index.ts +5 -0
- package/src/core/parser.ts +62 -0
- package/src/core/process-manager.ts +52 -0
- package/src/core/session.ts +423 -0
- package/src/core/tmux.ts +206 -0
- package/src/git/.gitkeep +0 -0
- package/src/git/index.ts +8 -0
- package/src/git/repo.ts +443 -0
- package/src/git/worktree.ts +317 -0
- package/src/github/.gitkeep +0 -0
- package/src/github/client.ts +208 -0
- package/src/github/index.ts +8 -0
- package/src/github/issues.ts +351 -0
- package/src/index.ts +369 -0
- package/src/prompts/.gitkeep +0 -0
- package/src/prompts/index.ts +1 -0
- package/src/prompts/swe-system.ts +22 -0
- package/src/providers/claude.ts +103 -0
- package/src/providers/index.ts +21 -0
- package/src/providers/opencode.ts +98 -0
- package/src/providers/registry.ts +53 -0
- package/src/providers/types.ts +117 -0
- package/src/store/buffers.ts +234 -0
- package/src/store/db.test.ts +579 -0
- package/src/store/db.ts +249 -0
- package/src/store/index.ts +101 -0
- package/src/store/project.ts +119 -0
- package/src/store/schema.sql +71 -0
- package/src/store/sessions.ts +454 -0
- package/src/store/types.ts +194 -0
- package/src/theme/context.tsx +170 -0
- package/src/theme/custom.ts +134 -0
- package/src/theme/index.ts +58 -0
- package/src/theme/loader.ts +264 -0
- package/src/theme/themes/aura.json +69 -0
- package/src/theme/themes/ayu.json +80 -0
- package/src/theme/themes/carbonfox.json +248 -0
- package/src/theme/themes/catppuccin-frappe.json +233 -0
- package/src/theme/themes/catppuccin-macchiato.json +233 -0
- package/src/theme/themes/catppuccin.json +112 -0
- package/src/theme/themes/cobalt2.json +228 -0
- package/src/theme/themes/cursor.json +249 -0
- package/src/theme/themes/dracula.json +219 -0
- package/src/theme/themes/everforest.json +241 -0
- package/src/theme/themes/flexoki.json +237 -0
- package/src/theme/themes/github.json +233 -0
- package/src/theme/themes/gruvbox.json +242 -0
- package/src/theme/themes/kanagawa.json +77 -0
- package/src/theme/themes/lucent-orng.json +237 -0
- package/src/theme/themes/material.json +235 -0
- package/src/theme/themes/matrix.json +77 -0
- package/src/theme/themes/mercury.json +252 -0
- package/src/theme/themes/monokai.json +221 -0
- package/src/theme/themes/nightowl.json +221 -0
- package/src/theme/themes/nord.json +223 -0
- package/src/theme/themes/one-dark.json +84 -0
- package/src/theme/themes/opencode.json +245 -0
- package/src/theme/themes/orng.json +249 -0
- package/src/theme/themes/osaka-jade.json +93 -0
- package/src/theme/themes/palenight.json +222 -0
- package/src/theme/themes/rosepine.json +234 -0
- package/src/theme/themes/solarized.json +223 -0
- package/src/theme/themes/synthwave84.json +226 -0
- package/src/theme/themes/tokyonight.json +243 -0
- package/src/theme/themes/vercel.json +245 -0
- package/src/theme/themes/vesper.json +218 -0
- package/src/theme/themes/zenburn.json +223 -0
- package/src/theme/types.ts +225 -0
- package/src/types/sql.d.ts +4 -0
- package/src/utils/ansi-parser.ts +225 -0
- package/src/utils/format.ts +46 -0
- package/src/utils/id.ts +15 -0
- package/src/utils/logger.ts +112 -0
- package/src/utils/prerequisites.ts +118 -0
- package/src/utils/shell.ts +9 -0
- package/src/wizard/flows.ts +419 -0
- package/src/wizard/index.ts +37 -0
- package/src/wizard/prompts.ts +190 -0
- package/src/workspace/detect.test.ts +51 -0
- package/src/workspace/detect.ts +223 -0
- package/src/workspace/index.ts +71 -0
- package/src/workspace/init.ts +131 -0
- package/src/workspace/paths.ts +143 -0
- package/src/workspace/project.ts +164 -0
- package/tsconfig.json +22 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# AGENTS.md - OpenSWE Agent Guidelines
|
|
2
|
+
|
|
3
|
+
Guidelines for AI agents working on OpenSWE - an AI-powered software engineering orchestration tool.
|
|
4
|
+
|
|
5
|
+
## Tech Stack
|
|
6
|
+
|
|
7
|
+
| Component | Tool | Notes |
|
|
8
|
+
|-----------|------|-------|
|
|
9
|
+
| Runtime | **Bun** (NOT Node.js) | Native SQLite, fast startup |
|
|
10
|
+
| Language | TypeScript (strict mode) | Use strict typing everywhere |
|
|
11
|
+
| TUI | @opentui/core + @opentui/solid | Solid.js reactivity |
|
|
12
|
+
| CLI Parser | yargs | |
|
|
13
|
+
| Prompts | @clack/prompts | First-run wizard |
|
|
14
|
+
| Database | SQLite via bun:sqlite | Built into Bun |
|
|
15
|
+
| Config | TOML via @iarna/toml | snake_case in files, camelCase in code |
|
|
16
|
+
| GitHub | gh CLI (shelled out) | Handles auth |
|
|
17
|
+
| Sessions | tmux | Process isolation, attach support |
|
|
18
|
+
|
|
19
|
+
**Build Requirement**: Zig must be installed (OpenTUI native dependency)
|
|
20
|
+
|
|
21
|
+
## Commands
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
bun install # Install dependencies
|
|
25
|
+
bun run dev # Development mode
|
|
26
|
+
bun src/index.ts # Direct execution
|
|
27
|
+
bun --hot src/index.ts # Hot reloading
|
|
28
|
+
|
|
29
|
+
bun run build # Build to dist/
|
|
30
|
+
|
|
31
|
+
bun test # Run all tests
|
|
32
|
+
bun test src/foo.test.ts # Single test file
|
|
33
|
+
bun test --watch # Watch mode
|
|
34
|
+
bun test --filter "pattern" # Filter tests
|
|
35
|
+
|
|
36
|
+
bunx tsc --noEmit # Type check without emit
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Iteration Finish
|
|
40
|
+
|
|
41
|
+
- Always run lint/type checks at the end of each iteration (`bunx tsc --noEmit` unless a dedicated lint script exists)
|
|
42
|
+
|
|
43
|
+
## Project Structure
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
src/
|
|
47
|
+
├── index.ts # CLI entry point with yargs
|
|
48
|
+
├── app.tsx # Main Solid.js TUI application
|
|
49
|
+
├── components/ # TUI components (SessionList, Preview, modals)
|
|
50
|
+
├── core/ # Session state machine, tmux manager, parser, queue
|
|
51
|
+
├── workspace/ # Detect/init workspace, path utilities
|
|
52
|
+
├── github/ # gh CLI wrapper, issues, PR creation
|
|
53
|
+
├── git/ # Clone, worktree operations
|
|
54
|
+
├── store/ # SQLite db, sessions/tasks/project CRUD
|
|
55
|
+
├── config/ # Types, global loader, defaults, env
|
|
56
|
+
├── prompts/ # SWE system prompt template
|
|
57
|
+
└── utils/ # Logger, ID generation, formatting
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Code Style
|
|
61
|
+
|
|
62
|
+
### Formatting
|
|
63
|
+
- **No semicolons**
|
|
64
|
+
- **1 tab indentation**
|
|
65
|
+
- **Double quotes** for strings
|
|
66
|
+
- **Trailing commas** in multiline structures
|
|
67
|
+
- **No emojis** in output, UI strings, or documentation
|
|
68
|
+
|
|
69
|
+
### Imports (in order)
|
|
70
|
+
1. Node.js/Bun built-ins (`os`, `path`, `fs/promises`)
|
|
71
|
+
2. External packages (`yargs`, `@iarna/toml`)
|
|
72
|
+
3. Internal with path alias (`@/*` for `src/*`)
|
|
73
|
+
4. Relative imports (`./`, `../`)
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { homedir } from "os"
|
|
77
|
+
import { parse as parseToml } from "@iarna/toml"
|
|
78
|
+
import type { GlobalConfig } from "@/config/types"
|
|
79
|
+
import { logger } from "./logger"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Types
|
|
83
|
+
- **Strict mode** - use strict typing everywhere possible; never use `any` without justification
|
|
84
|
+
- **Explicit return types** on exported functions
|
|
85
|
+
- **Type literals** for constrained values
|
|
86
|
+
- **Type guards** for runtime validation
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
export type Phase = "pending" | "research" | "planning" | "coding" | "testing" | "pr_creation" | "completed" | "failed"
|
|
90
|
+
export type Status = "queued" | "active" | "paused" | "needs_attention" | "completed" | "failed"
|
|
91
|
+
|
|
92
|
+
export function isValidPhase(val: unknown): val is Phase {
|
|
93
|
+
return typeof val === "string" && VALID_PHASES.includes(val as Phase)
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Naming
|
|
98
|
+
| Element | Convention | Example |
|
|
99
|
+
|---------|------------|---------|
|
|
100
|
+
| Files | kebab-case or camelCase | `session.ts`, `swe-system.ts` |
|
|
101
|
+
| Types/Interfaces | PascalCase | `Session`, `HumanTask` |
|
|
102
|
+
| Functions | camelCase | `loadConfig`, `createSession` |
|
|
103
|
+
| Constants | SCREAMING_SNAKE_CASE | `DEFAULT_CONFIG` |
|
|
104
|
+
|
|
105
|
+
### Error Handling
|
|
106
|
+
- **try-catch** for async operations that may fail
|
|
107
|
+
- **Graceful degradation** - return sensible defaults
|
|
108
|
+
- **Log warnings** for non-fatal issues
|
|
109
|
+
- **Throw errors** only for fatal conditions
|
|
110
|
+
|
|
111
|
+
### Documentation
|
|
112
|
+
```typescript
|
|
113
|
+
/**
|
|
114
|
+
* Load and merge configuration from all sources
|
|
115
|
+
* @param cliOverrides - Optional CLI flag overrides
|
|
116
|
+
* @returns Fully resolved configuration
|
|
117
|
+
*/
|
|
118
|
+
export async function loadConfig(cliOverrides?: CLIOverrides): Promise<GlobalConfig>
|
|
119
|
+
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// Section Headers
|
|
122
|
+
// ============================================================================
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Bun-Specific APIs
|
|
126
|
+
|
|
127
|
+
Prefer Bun APIs over Node.js equivalents:
|
|
128
|
+
|
|
129
|
+
| Use This | Instead Of |
|
|
130
|
+
|----------|------------|
|
|
131
|
+
| `Bun.file()` / `Bun.write()` | `fs.readFile` / `fs.writeFile` |
|
|
132
|
+
| `Bun.$\`cmd\`` | `child_process`, `execa` |
|
|
133
|
+
| `bun:sqlite` | `better-sqlite3` |
|
|
134
|
+
| `Bun.serve()` | `express` |
|
|
135
|
+
|
|
136
|
+
Environment variables auto-load from `.env` - don't use `dotenv`.
|
|
137
|
+
|
|
138
|
+
## Key Data Models
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
interface Session {
|
|
142
|
+
id: string
|
|
143
|
+
name: string
|
|
144
|
+
issueNumber: number | null
|
|
145
|
+
worktreePath: string // .worktrees/issue-123
|
|
146
|
+
branchName: string // openswe/issue-123
|
|
147
|
+
phase: Phase
|
|
148
|
+
status: Status
|
|
149
|
+
attentionReason: string | null
|
|
150
|
+
retryCount: number // 0-2, then needs_attention
|
|
151
|
+
tokensUsed: number
|
|
152
|
+
prUrl: string | null
|
|
153
|
+
pid: number | null
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
interface HumanTask {
|
|
157
|
+
id: string
|
|
158
|
+
sessionId: string
|
|
159
|
+
type: "question" | "permission" | "blocker" | "retry_failed" | "pr_review"
|
|
160
|
+
priority: "high" | "medium" | "low"
|
|
161
|
+
title: string
|
|
162
|
+
context: string
|
|
163
|
+
rawOutput: string
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Configuration Precedence
|
|
168
|
+
|
|
169
|
+
1. CLI flags (highest): `--backend`, `--max-sessions`, `--debug`
|
|
170
|
+
2. Environment variables: `OPENSWE_BACKEND`, `OPENSWE_LOG_LEVEL`, etc.
|
|
171
|
+
3. Global config file: `~/.config/openswe/config.toml`
|
|
172
|
+
4. Built-in defaults (lowest)
|
|
173
|
+
|
|
174
|
+
## Testing
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { test, expect, describe } from "bun:test"
|
|
178
|
+
|
|
179
|
+
describe("Session", () => {
|
|
180
|
+
test("creates session with pending phase", async () => {
|
|
181
|
+
const session = await createSession({ name: "test" })
|
|
182
|
+
expect(session.phase).toBe("pending")
|
|
183
|
+
expect(session.status).toBe("queued")
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Workspace Model
|
|
189
|
+
|
|
190
|
+
- **Project-local**: Each workspace tied to single repo
|
|
191
|
+
- **Directory-based**: User chooses where to work
|
|
192
|
+
- **Worktrees**: Sessions isolated in `.worktrees/{issue-number}/`
|
|
193
|
+
- **State**: Project state in `.openswe/state.db`
|
|
194
|
+
|
|
195
|
+
Detection logic:
|
|
196
|
+
1. `.openswe/` exists → Load existing project
|
|
197
|
+
2. `.git/` exists → Offer to adopt repo
|
|
198
|
+
3. `--repo` flag → Clone to current dir
|
|
199
|
+
4. Empty dir → Run setup wizard
|
|
200
|
+
|
|
201
|
+
## WIP
|
|
202
|
+
|
|
203
|
+
This project is a WIP, meaning you can overwrite code and make db schema changes. Ensure that best coding practices are followed, even if it means having to reset the local db or make breaking code changes.
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# AGENTS.md - OpenSWE Agent Guidelines
|
|
2
|
+
|
|
3
|
+
Guidelines for AI agents working on OpenSWE - an AI-powered software engineering orchestration tool.
|
|
4
|
+
|
|
5
|
+
## Tech Stack
|
|
6
|
+
|
|
7
|
+
| Component | Tool | Notes |
|
|
8
|
+
|-----------|------|-------|
|
|
9
|
+
| Runtime | **Bun** (NOT Node.js) | Native SQLite, fast startup |
|
|
10
|
+
| Language | TypeScript (strict mode) | Use strict typing everywhere |
|
|
11
|
+
| TUI | @opentui/core + @opentui/solid | Solid.js reactivity |
|
|
12
|
+
| CLI Parser | yargs | |
|
|
13
|
+
| Prompts | @clack/prompts | First-run wizard |
|
|
14
|
+
| Database | SQLite via bun:sqlite | Built into Bun |
|
|
15
|
+
| Config | TOML via @iarna/toml | snake_case in files, camelCase in code |
|
|
16
|
+
| GitHub | gh CLI (shelled out) | Handles auth |
|
|
17
|
+
| Sessions | tmux | Process isolation, attach support |
|
|
18
|
+
|
|
19
|
+
**Build Requirement**: Zig must be installed (OpenTUI native dependency)
|
|
20
|
+
|
|
21
|
+
## Commands
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
bun install # Install dependencies
|
|
25
|
+
bun run dev # Development mode
|
|
26
|
+
bun src/index.ts # Direct execution
|
|
27
|
+
bun --hot src/index.ts # Hot reloading
|
|
28
|
+
|
|
29
|
+
bun run build # Build to dist/
|
|
30
|
+
|
|
31
|
+
bun test # Run all tests
|
|
32
|
+
bun test src/foo.test.ts # Single test file
|
|
33
|
+
bun test --watch # Watch mode
|
|
34
|
+
bun test --filter "pattern" # Filter tests
|
|
35
|
+
|
|
36
|
+
bunx tsc --noEmit # Type check without emit
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Iteration Finish
|
|
40
|
+
|
|
41
|
+
- Always run lint/type checks at the end of each iteration (`bunx tsc --noEmit` unless a dedicated lint script exists)
|
|
42
|
+
|
|
43
|
+
## Project Structure
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
src/
|
|
47
|
+
├── index.ts # CLI entry point with yargs
|
|
48
|
+
├── app.tsx # Main Solid.js TUI application
|
|
49
|
+
├── components/ # TUI components (SessionList, Preview, modals)
|
|
50
|
+
├── core/ # Session state machine, tmux manager, parser, queue
|
|
51
|
+
├── workspace/ # Detect/init workspace, path utilities
|
|
52
|
+
├── github/ # gh CLI wrapper, issues, PR creation
|
|
53
|
+
├── git/ # Clone, worktree operations
|
|
54
|
+
├── store/ # SQLite db, sessions/tasks/project CRUD
|
|
55
|
+
├── config/ # Types, global loader, defaults, env
|
|
56
|
+
├── prompts/ # SWE system prompt template
|
|
57
|
+
└── utils/ # Logger, ID generation, formatting
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Code Style
|
|
61
|
+
|
|
62
|
+
### Formatting
|
|
63
|
+
- **No semicolons**
|
|
64
|
+
- **1-tab indentation**
|
|
65
|
+
- **Double quotes** for strings
|
|
66
|
+
- **Trailing commas** in multiline structures
|
|
67
|
+
- **No emojis** in output, UI strings, or documentation
|
|
68
|
+
|
|
69
|
+
### Imports (in order)
|
|
70
|
+
1. Node.js/Bun built-ins (`os`, `path`, `fs/promises`)
|
|
71
|
+
2. External packages (`yargs`, `@iarna/toml`)
|
|
72
|
+
3. Internal with path alias (`@/*` for `src/*`)
|
|
73
|
+
4. Relative imports (`./`, `../`)
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { homedir } from "os"
|
|
77
|
+
import { parse as parseToml } from "@iarna/toml"
|
|
78
|
+
import type { GlobalConfig } from "@/config/types"
|
|
79
|
+
import { logger } from "./logger"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Types
|
|
83
|
+
- **Strict mode** - use strict typing everywhere possible; never use `any` without justification
|
|
84
|
+
- **Explicit return types** on exported functions
|
|
85
|
+
- **Type literals** for constrained values
|
|
86
|
+
- **Type guards** for runtime validation
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
export type Phase = "pending" | "research" | "planning" | "coding" | "testing" | "pr_creation" | "completed" | "failed"
|
|
90
|
+
export type Status = "queued" | "active" | "paused" | "needs_attention" | "completed" | "failed"
|
|
91
|
+
|
|
92
|
+
export function isValidPhase(val: unknown): val is Phase {
|
|
93
|
+
return typeof val === "string" && VALID_PHASES.includes(val as Phase)
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Naming
|
|
98
|
+
| Element | Convention | Example |
|
|
99
|
+
|---------|------------|---------|
|
|
100
|
+
| Files | kebab-case or camelCase | `session.ts`, `swe-system.ts` |
|
|
101
|
+
| Types/Interfaces | PascalCase | `Session`, `HumanTask` |
|
|
102
|
+
| Functions | camelCase | `loadConfig`, `createSession` |
|
|
103
|
+
| Constants | SCREAMING_SNAKE_CASE | `DEFAULT_CONFIG` |
|
|
104
|
+
|
|
105
|
+
### Error Handling
|
|
106
|
+
- **try-catch** for async operations that may fail
|
|
107
|
+
- **Graceful degradation** - return sensible defaults
|
|
108
|
+
- **Log warnings** for non-fatal issues
|
|
109
|
+
- **Throw errors** only for fatal conditions
|
|
110
|
+
|
|
111
|
+
### Documentation
|
|
112
|
+
```typescript
|
|
113
|
+
/**
|
|
114
|
+
* Load and merge configuration from all sources
|
|
115
|
+
* @param cliOverrides - Optional CLI flag overrides
|
|
116
|
+
* @returns Fully resolved configuration
|
|
117
|
+
*/
|
|
118
|
+
export async function loadConfig(cliOverrides?: CLIOverrides): Promise<GlobalConfig>
|
|
119
|
+
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// Section Headers
|
|
122
|
+
// ============================================================================
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Bun-Specific APIs
|
|
126
|
+
|
|
127
|
+
Prefer Bun APIs over Node.js equivalents:
|
|
128
|
+
|
|
129
|
+
| Use This | Instead Of |
|
|
130
|
+
|----------|------------|
|
|
131
|
+
| `Bun.file()` / `Bun.write()` | `fs.readFile` / `fs.writeFile` |
|
|
132
|
+
| `Bun.$\`cmd\`` | `child_process`, `execa` |
|
|
133
|
+
| `bun:sqlite` | `better-sqlite3` |
|
|
134
|
+
| `Bun.serve()` | `express` |
|
|
135
|
+
|
|
136
|
+
Environment variables auto-load from `.env` - don't use `dotenv`.
|
|
137
|
+
|
|
138
|
+
## Key Data Models
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
interface Session {
|
|
142
|
+
id: string
|
|
143
|
+
name: string
|
|
144
|
+
issueNumber: number | null
|
|
145
|
+
worktreePath: string // .worktrees/issue-123
|
|
146
|
+
branchName: string // openswe/issue-123
|
|
147
|
+
phase: Phase
|
|
148
|
+
status: Status
|
|
149
|
+
attentionReason: string | null
|
|
150
|
+
retryCount: number // 0-2, then needs_attention
|
|
151
|
+
tokensUsed: number
|
|
152
|
+
prUrl: string | null
|
|
153
|
+
pid: number | null
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
interface HumanTask {
|
|
157
|
+
id: string
|
|
158
|
+
sessionId: string
|
|
159
|
+
type: "question" | "permission" | "blocker" | "retry_failed" | "pr_review"
|
|
160
|
+
priority: "high" | "medium" | "low"
|
|
161
|
+
title: string
|
|
162
|
+
context: string
|
|
163
|
+
rawOutput: string
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Configuration Precedence
|
|
168
|
+
|
|
169
|
+
1. CLI flags (highest): `--backend`, `--max-sessions`, `--debug`
|
|
170
|
+
2. Environment variables: `OPENSWE_BACKEND`, `OPENSWE_LOG_LEVEL`, etc.
|
|
171
|
+
3. Global config file: `~/.config/openswe/config.toml`
|
|
172
|
+
4. Built-in defaults (lowest)
|
|
173
|
+
|
|
174
|
+
## Testing
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { test, expect, describe } from "bun:test"
|
|
178
|
+
|
|
179
|
+
describe("Session", () => {
|
|
180
|
+
test("creates session with pending phase", async () => {
|
|
181
|
+
const session = await createSession({ name: "test" })
|
|
182
|
+
expect(session.phase).toBe("pending")
|
|
183
|
+
expect(session.status).toBe("queued")
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Workspace Model
|
|
189
|
+
|
|
190
|
+
- **Project-local**: Each workspace tied to single repo
|
|
191
|
+
- **Directory-based**: User chooses where to work
|
|
192
|
+
- **Worktrees**: Sessions isolated in `.worktrees/{issue-number}/`
|
|
193
|
+
- **State**: Project state in `.openswe/state.db`
|
|
194
|
+
|
|
195
|
+
Detection logic:
|
|
196
|
+
1. `.openswe/` exists → Load existing project
|
|
197
|
+
2. `.git/` exists → Offer to adopt repo
|
|
198
|
+
3. `--repo` flag → Clone to current dir
|
|
199
|
+
4. Empty dir → Run setup wizard
|
|
200
|
+
|
|
201
|
+
## WIP
|
|
202
|
+
|
|
203
|
+
This project is a WIP, meaning you can overwrite code and make db schema changes. Ensure that best coding practices are followed, even if it means having to reset the local db or make breaking code changes.
|
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# openswe
|
|
2
|
+
|
|
3
|
+
openswe is an AI coding agent (opencode, claude code) orchestration tool. It connects to github, fetches open issues, and starts working on them for you.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Bun (runtime)
|
|
8
|
+
- Zig (required to build OpenTUI native dependency)
|
|
9
|
+
- tmux (session management)
|
|
10
|
+
- Git
|
|
11
|
+
- GitHub CLI (`gh`) with an authenticated account
|
|
12
|
+
- macOS or Linux (TUI dependencies assume a POSIX environment)
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
git clone <repo-url>
|
|
18
|
+
cd openswe
|
|
19
|
+
bun install
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Installation as Command
|
|
23
|
+
|
|
24
|
+
To run `openswe` from anywhere in your terminal:
|
|
25
|
+
|
|
26
|
+
### Option 1: Development Link (Recommended for contributors)
|
|
27
|
+
|
|
28
|
+
This links the current project directory so changes are reflected immediately.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cd openswe
|
|
32
|
+
chmod +x src/index.ts
|
|
33
|
+
bun link
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
You can now run `openswe` from any directory.
|
|
37
|
+
|
|
38
|
+
### Option 2: Standalone Binary (Compiled)
|
|
39
|
+
|
|
40
|
+
To create a single executable file that can be moved anywhere (even to machines without Bun installed):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
bun build ./src/index.ts --compile --outfile openswe
|
|
44
|
+
mv openswe /usr/local/bin/
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Option 3: Manual Linking
|
|
48
|
+
|
|
49
|
+
If you prefer to manually link the script:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
chmod +x src/index.ts
|
|
53
|
+
ln -s $(pwd)/src/index.ts /usr/local/bin/openswe
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Option 4: Bun Global Install
|
|
57
|
+
|
|
58
|
+
You can install it globally from the local folder:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
bun add -g .
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Quick Start
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
bun run dev
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
If you want to run directly without the dev script:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
bun src/index.ts
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## CLI Usage
|
|
77
|
+
|
|
78
|
+
Run `openswe` with the following options:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
bun src/index.ts [options]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Options:
|
|
85
|
+
|
|
86
|
+
- `--repo`, `-r`: GitHub repo in `owner/repo` format (used in setup wizard)
|
|
87
|
+
- `--setup`: Force re-run the setup wizard
|
|
88
|
+
- `--status`: Show project status without launching the TUI
|
|
89
|
+
- `--backend`: AI backend (`opencode` or `claude`)
|
|
90
|
+
- `--max-sessions`: Maximum concurrent sessions
|
|
91
|
+
- `--debug`: Enable debug logging
|
|
92
|
+
|
|
93
|
+
Examples:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
bun src/index.ts --repo owner/repo
|
|
97
|
+
bun src/index.ts --status
|
|
98
|
+
bun src/index.ts --backend opencode --max-sessions 3
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Configuration
|
|
102
|
+
|
|
103
|
+
OpenSWE supports configuration via CLI flags, environment variables, and a global config file. Precedence is:
|
|
104
|
+
|
|
105
|
+
1. CLI flags (highest)
|
|
106
|
+
2. Environment variables
|
|
107
|
+
3. Global config file: `~/.config/openswe/config.toml`
|
|
108
|
+
4. Built-in defaults (lowest)
|
|
109
|
+
|
|
110
|
+
### Environment Variables
|
|
111
|
+
|
|
112
|
+
- `OPENSWE_BACKEND`: `opencode` or `claude`
|
|
113
|
+
- `OPENSWE_MAX_SESSIONS`: positive integer
|
|
114
|
+
- `OPENSWE_LOG_LEVEL`: `debug`, `info`, `warn`, or `error`
|
|
115
|
+
- `OPENSWE_PR_AUTO_CREATE`: `true` or `false`
|
|
116
|
+
- `OPENSWE_PR_DRAFT`: `true` or `false`
|
|
117
|
+
|
|
118
|
+
## Workspace Behavior
|
|
119
|
+
|
|
120
|
+
OpenSWE detects the working directory and chooses a setup path:
|
|
121
|
+
|
|
122
|
+
1. `.openswe/` exists: load existing project
|
|
123
|
+
2. `.git/` exists: offer to adopt the repo
|
|
124
|
+
3. `--repo` flag: clone into current directory
|
|
125
|
+
4. Empty directory: run setup wizard
|
|
126
|
+
|
|
127
|
+
Sessions run inside Git worktrees under `.worktrees/{issue-number}/` and project state lives in `.openswe/state.db`.
|
|
128
|
+
|
|
129
|
+
## Scripts
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
bun run dev # Run the CLI in development mode
|
|
133
|
+
bun run build # Build to dist/
|
|
134
|
+
bun test # Run all tests
|
|
135
|
+
bunx tsc --noEmit # Type check (required after each iteration)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Project Structure
|
|
139
|
+
|
|
140
|
+
```text
|
|
141
|
+
src/
|
|
142
|
+
├── index.ts # CLI entry point with yargs
|
|
143
|
+
├── app.tsx # Main Solid.js TUI application
|
|
144
|
+
├── components/ # TUI components (SessionList, Preview, modals)
|
|
145
|
+
├── core/ # Session state machine, tmux manager, parser, queue
|
|
146
|
+
├── workspace/ # Detect/init workspace, path utilities
|
|
147
|
+
├── github/ # gh CLI wrapper, issues, PR creation
|
|
148
|
+
├── git/ # Clone, worktree operations
|
|
149
|
+
├── store/ # SQLite db, sessions/tasks/project CRUD
|
|
150
|
+
├── config/ # Types, global loader, defaults, env
|
|
151
|
+
├── prompts/ # SWE system prompt template
|
|
152
|
+
└── utils/ # Logger, ID generation, formatting
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Build Output
|
|
156
|
+
|
|
157
|
+
The build outputs a Bun-targeted bundle in `dist/`:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
bun run build
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Troubleshooting
|
|
164
|
+
|
|
165
|
+
- If `@opentui/core` fails to install/build, verify Zig is installed and available in `PATH`.
|
|
166
|
+
- If setup fails, confirm `gh auth status` shows an authenticated GitHub account.
|