@lovenyberg/ove 0.1.1 → 0.2.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/CLAUDE.md +4 -3
- package/README.md +38 -6
- package/config.example.json +3 -0
- package/docs/examples.md +65 -3
- package/docs/index.html +24 -8
- package/docs/plans/2026-02-21-codex-runner-design.md +51 -0
- package/docs/plans/2026-02-21-codex-runner-plan.md +475 -0
- package/package.json +1 -1
- package/src/config.test.ts +52 -2
- package/src/config.ts +39 -1
- package/src/index.ts +76 -12
- package/src/router.test.ts +25 -0
- package/src/router.ts +11 -0
- package/src/runner.ts +1 -0
- package/src/runners/codex.test.ts +85 -0
- package/src/runners/codex.ts +137 -0
- package/src/setup.test.ts +87 -20
- package/src/setup.ts +180 -54
package/CLAUDE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Ove
|
|
2
2
|
|
|
3
|
-
Your grumpy but meticulous dev companion — routes chat messages to Claude Code CLI in isolated worktrees.
|
|
3
|
+
Your grumpy but meticulous dev companion — routes chat messages to AI coding agents (Claude Code CLI or OpenAI Codex CLI) in isolated worktrees.
|
|
4
4
|
|
|
5
5
|
## Stack
|
|
6
6
|
- Bun + TypeScript
|
|
@@ -11,12 +11,13 @@ Your grumpy but meticulous dev companion — routes chat messages to Claude Code
|
|
|
11
11
|
- Bun.serve for HTTP API + Web UI
|
|
12
12
|
- gh CLI for GitHub polling
|
|
13
13
|
- bun:sqlite for task queue
|
|
14
|
-
- claude -p CLI for code tasks
|
|
14
|
+
- claude -p CLI for code tasks (default runner)
|
|
15
|
+
- codex exec CLI for code tasks (alternative runner)
|
|
15
16
|
|
|
16
17
|
## Structure
|
|
17
18
|
- src/adapters/ — chat platform adapters (Slack, WhatsApp, Telegram, Discord, CLI) and event adapters (GitHub, HTTP API)
|
|
18
19
|
- src/queue.ts — SQLite task queue
|
|
19
|
-
- src/runners/ — agent runner implementations (Claude,
|
|
20
|
+
- src/runners/ — agent runner implementations (Claude, Codex)
|
|
20
21
|
- src/repos.ts — git clone/pull/worktree management
|
|
21
22
|
- src/router.ts — message → task mapping
|
|
22
23
|
- src/config.ts — repo/user configuration
|
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
Talk to Ove from Slack, WhatsApp, Telegram, Discord, GitHub issues, a Web UI, or the terminal — he'll grumble about it, but he'll review your PRs, fix your issues, run your tests, brainstorm ideas, and scaffold new projects. Properly.
|
|
15
15
|
|
|
16
|
+
**Just chat.** You don't need to memorize commands. Talk to Ove like you'd talk to a colleague — ask questions, describe what you need, paste error messages, think out loud. He understands natural language. The commands below are shortcuts, not requirements.
|
|
17
|
+
|
|
16
18
|
## Quick Start
|
|
17
19
|
|
|
18
20
|
```bash
|
|
@@ -23,11 +25,23 @@ ove start
|
|
|
23
25
|
|
|
24
26
|
## Prerequisites
|
|
25
27
|
|
|
26
|
-
- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated
|
|
28
|
+
- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated (default runner)
|
|
29
|
+
- Or [OpenAI Codex CLI](https://github.com/openai/codex) installed and authenticated (alternative runner)
|
|
27
30
|
- [GitHub CLI](https://cli.github.com) (`gh`) installed and authenticated
|
|
28
31
|
- SSH access to your git repos
|
|
29
32
|
|
|
30
|
-
##
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
Talk to Ove the way you'd talk to a teammate. These all work:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
"can you check what's failing in the auth tests on my-app?"
|
|
39
|
+
"the login page is broken, users get a 500 after submitting"
|
|
40
|
+
"how does the payment webhook work in my-app?"
|
|
41
|
+
"refactor the user service, it's getting messy"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Ove figures out the intent, picks the right repo, and gets to work. For common tasks, there are also shorthand commands:
|
|
31
45
|
|
|
32
46
|
```
|
|
33
47
|
review PR #N on <repo> Code review with inline comments
|
|
@@ -60,7 +74,7 @@ ove init
|
|
|
60
74
|
ove start
|
|
61
75
|
```
|
|
62
76
|
|
|
63
|
-
Requires [Bun](https://bun.sh), Claude Code CLI, and GitHub CLI on your machine.
|
|
77
|
+
Requires [Bun](https://bun.sh), Claude Code CLI (or Codex CLI), and GitHub CLI on your machine.
|
|
64
78
|
|
|
65
79
|
### Docker
|
|
66
80
|
|
|
@@ -70,11 +84,11 @@ docker compose up -d # start container
|
|
|
70
84
|
docker compose logs -f # watch logs
|
|
71
85
|
```
|
|
72
86
|
|
|
73
|
-
The image includes Bun, git, and Claude CLI. Mounts `config.json`, `.env`, `repos/`, and SSH keys from the host.
|
|
87
|
+
The image includes Bun, git, and Claude CLI (install Codex CLI separately if needed). Mounts `config.json`, `.env`, `repos/`, and SSH keys from the host.
|
|
74
88
|
|
|
75
89
|
### VM
|
|
76
90
|
|
|
77
|
-
Ove runs well on a small VM (2 CPU, 4 GB RAM). Install Bun, Claude Code, and GitHub CLI, then run as a systemd service:
|
|
91
|
+
Ove runs well on a small VM (2 CPU, 4 GB RAM). Install Bun, Claude Code (or Codex CLI), and GitHub CLI, then run as a systemd service:
|
|
78
92
|
|
|
79
93
|
```bash
|
|
80
94
|
git clone git@github.com:jacksoncage/ove.git && cd ove
|
|
@@ -146,6 +160,7 @@ sudo systemctl enable --now ove
|
|
|
146
160
|
"cli:local": { "name": "alice", "repos": ["my-app"] }
|
|
147
161
|
},
|
|
148
162
|
"claude": { "maxTurns": 10 },
|
|
163
|
+
"runner": { "name": "claude" },
|
|
149
164
|
"cron": [
|
|
150
165
|
{
|
|
151
166
|
"schedule": "0 9 * * 1-5",
|
|
@@ -157,6 +172,23 @@ sudo systemctl enable --now ove
|
|
|
157
172
|
}
|
|
158
173
|
```
|
|
159
174
|
|
|
175
|
+
### Runner Selection
|
|
176
|
+
|
|
177
|
+
By default Ove uses Claude Code CLI. To use OpenAI Codex instead, set the `runner` field globally or per-repo:
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"runner": { "name": "codex", "model": "o3" },
|
|
182
|
+
"repos": {
|
|
183
|
+
"my-app": {
|
|
184
|
+
"runner": { "name": "claude" }
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Per-repo `runner` overrides the global default. Supported runners: `"claude"` (default), `"codex"`.
|
|
191
|
+
|
|
160
192
|
Static cron jobs go in `config.json`. Users can also create schedules via chat — these are stored in SQLite and managed with `list schedules` / `remove schedule #N`.
|
|
161
193
|
|
|
162
194
|
## Testing
|
|
@@ -172,7 +204,7 @@ bun test # 150 tests
|
|
|
172
204
|
3. Router parses intent and extracts repo/args
|
|
173
205
|
4. Task gets queued in SQLite (one per repo at a time)
|
|
174
206
|
5. Worker creates an isolated git worktree
|
|
175
|
-
6. Runs `claude -p` with streaming
|
|
207
|
+
6. Runs the configured agent runner (`claude -p` or `codex exec`) with streaming JSON output
|
|
176
208
|
7. Status updates stream back (chat: edits a message, HTTP: SSE, GitHub: single comment)
|
|
177
209
|
8. Result sent back, worktree cleaned up
|
|
178
210
|
|
package/config.example.json
CHANGED
package/docs/examples.md
CHANGED
|
@@ -1,8 +1,56 @@
|
|
|
1
1
|
# Example Interactions
|
|
2
2
|
|
|
3
|
-
Examples showing Ove across different transports
|
|
3
|
+
Examples showing Ove across different transports. You can use shorthand commands or just chat naturally — Ove understands both.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Natural Conversation
|
|
6
|
+
|
|
7
|
+
You don't need commands. Just describe what you need, like you'd tell a colleague.
|
|
8
|
+
|
|
9
|
+
**Slack DM:**
|
|
10
|
+
```
|
|
11
|
+
alice: the login page is broken, users get a 500 after submitting the form
|
|
12
|
+
ove: Task queued (aaa11111). Working on it...
|
|
13
|
+
> Grep: "login" in src/
|
|
14
|
+
> Read: src/routes/auth.ts
|
|
15
|
+
> Read: src/middleware/session.ts
|
|
16
|
+
ove: Found the issue — the session middleware wasn't awaiting the
|
|
17
|
+
database call on line 34 of src/middleware/session.ts. Created
|
|
18
|
+
PR #47 with the fix and added a test:
|
|
19
|
+
https://github.com/org/my-app/pull/47
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Telegram:**
|
|
23
|
+
```
|
|
24
|
+
alice: can you add input validation to the user registration endpoint in my-app?
|
|
25
|
+
ove: Task queued (bbb22222). Working on it...
|
|
26
|
+
> Read: src/routes/users.ts
|
|
27
|
+
> Edit: src/routes/users.ts
|
|
28
|
+
> Write: src/routes/users.test.ts
|
|
29
|
+
> Bash: bun test
|
|
30
|
+
ove: Done. Added zod validation for email, password length, and
|
|
31
|
+
username format. All 48 tests pass. PR #48:
|
|
32
|
+
https://github.com/org/my-app/pull/48
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Discord:**
|
|
36
|
+
```
|
|
37
|
+
alice: how does the caching layer work in my-app? I need to understand
|
|
38
|
+
it before I make changes
|
|
39
|
+
ove: Looking into it...
|
|
40
|
+
> Glob: **/*cache*
|
|
41
|
+
> Read: src/cache/redis.ts
|
|
42
|
+
> Read: src/cache/keys.ts
|
|
43
|
+
> Read: src/middleware/cache.ts
|
|
44
|
+
ove: The caching layer has 3 parts:
|
|
45
|
+
1. src/cache/redis.ts — Redis client wrapper with connection pooling
|
|
46
|
+
2. src/cache/keys.ts — key generation with TTL per resource type
|
|
47
|
+
3. src/middleware/cache.ts — Express middleware that caches GET
|
|
48
|
+
responses by URL + user role
|
|
49
|
+
Cache invalidation happens on POST/PUT/DELETE via the afterWrite
|
|
50
|
+
hook in the base repository class.
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## PR Review (shorthand)
|
|
6
54
|
|
|
7
55
|
**Slack DM:**
|
|
8
56
|
```
|
|
@@ -128,7 +176,9 @@ alice: remove schedule #1
|
|
|
128
176
|
ove: Schedule #1 removed.
|
|
129
177
|
```
|
|
130
178
|
|
|
131
|
-
## Free-form
|
|
179
|
+
## More Free-form Examples
|
|
180
|
+
|
|
181
|
+
Anything you type works. Ove parses intent from natural language.
|
|
132
182
|
|
|
133
183
|
```
|
|
134
184
|
alice: what does the auth middleware do in my-app
|
|
@@ -143,6 +193,18 @@ ove: The auth middleware in my-app:
|
|
|
143
193
|
Located in src/middleware/auth.ts (42 lines).
|
|
144
194
|
```
|
|
145
195
|
|
|
196
|
+
```
|
|
197
|
+
alice: the CI is red on main, can you check what's going on?
|
|
198
|
+
ove: Task queued (ggg77777). Working on it...
|
|
199
|
+
> Bash: gh run list --limit 5
|
|
200
|
+
> Bash: gh run view 12345 --log-failed
|
|
201
|
+
> Read: src/api.test.ts
|
|
202
|
+
ove: The test "should return 404 for unknown routes" is failing
|
|
203
|
+
because the new /health endpoint was added without updating
|
|
204
|
+
the route count assertion. Line 89 in src/api.test.ts expects
|
|
205
|
+
12 routes but there are now 13. Want me to fix it?
|
|
206
|
+
```
|
|
207
|
+
|
|
146
208
|
## HTTP API
|
|
147
209
|
|
|
148
210
|
**Send a task via curl:**
|
package/docs/index.html
CHANGED
|
@@ -593,8 +593,8 @@
|
|
|
593
593
|
<h1>Ove</h1>
|
|
594
594
|
<div class="hero-subtitle">Dev companion</div>
|
|
595
595
|
<p class="hero-quote">
|
|
596
|
-
"
|
|
597
|
-
<span>— Ove, on every
|
|
596
|
+
"Just tell me what's wrong. I'll figure it out."
|
|
597
|
+
<span>— Ove, on every conversation</span>
|
|
598
598
|
</p>
|
|
599
599
|
<div class="hero-actions">
|
|
600
600
|
<a class="btn" href="#getting-started">Get started</a>
|
|
@@ -620,6 +620,15 @@
|
|
|
620
620
|
<h2>What Ove Does</h2>
|
|
621
621
|
<p class="section-note">He grumbles, but he gets it done. Properly.</p>
|
|
622
622
|
|
|
623
|
+
<p>Talk to Ove like you'd talk to a colleague. Ask questions, describe problems, paste error logs, think out loud — he understands natural language. No need to memorize commands. Just chat.</p>
|
|
624
|
+
|
|
625
|
+
<pre data-label="just chat">"the login page throws a 500 after submitting"
|
|
626
|
+
"can you check what's breaking the auth tests on my-app?"
|
|
627
|
+
"how does the payment webhook work?"
|
|
628
|
+
"refactor the user service, it's getting messy"</pre>
|
|
629
|
+
|
|
630
|
+
<p>Ove figures out the intent, picks the right repo, and gets to work. For common tasks, there are also shorthand commands — but they're shortcuts, not requirements.</p>
|
|
631
|
+
|
|
623
632
|
<div class="features">
|
|
624
633
|
<div class="feature">
|
|
625
634
|
<div class="feature-label">01 — Review</div>
|
|
@@ -671,7 +680,8 @@
|
|
|
671
680
|
|
|
672
681
|
<h3>Prerequisites</h3>
|
|
673
682
|
<ol class="steps">
|
|
674
|
-
<li><a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code CLI</a> installed and authenticated</li>
|
|
683
|
+
<li><a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code CLI</a> installed and authenticated (default runner)</li>
|
|
684
|
+
<li>Or <a href="https://github.com/openai/codex">OpenAI Codex CLI</a> installed and authenticated (alternative runner)</li>
|
|
675
685
|
<li><a href="https://cli.github.com">GitHub CLI</a> (<code>gh</code>) installed and authenticated</li>
|
|
676
686
|
<li>SSH access to your Git repos</li>
|
|
677
687
|
</ol>
|
|
@@ -721,6 +731,7 @@ sudo systemctl enable --now ove</pre>
|
|
|
721
731
|
"cli:local": { "name": "alice", "repos": ["my-app"] }
|
|
722
732
|
},
|
|
723
733
|
"claude": { "maxTurns": 10 },
|
|
734
|
+
"runner": { "name": "claude" },
|
|
724
735
|
"cron": [
|
|
725
736
|
{
|
|
726
737
|
"schedule": "0 9 * * 1-5",
|
|
@@ -731,6 +742,8 @@ sudo systemctl enable --now ove</pre>
|
|
|
731
742
|
]
|
|
732
743
|
}</pre>
|
|
733
744
|
|
|
745
|
+
<p>Set <code>"runner"</code> globally to <code>{"name": "codex"}</code> to use OpenAI Codex, or override per-repo with a <code>"runner"</code> field inside the repo config. Supported runners: <code>claude</code> (default), <code>codex</code>.</p>
|
|
746
|
+
|
|
734
747
|
<p>Static cron jobs go in <code>config.json</code>. Users can also create schedules from chat — just say something like <code>lint and check every day at 9</code>. These are stored in SQLite and managed with <code>list schedules</code> / <code>remove schedule #N</code>.</p>
|
|
735
748
|
|
|
736
749
|
<div class="ove-says">
|
|
@@ -741,7 +754,7 @@ sudo systemctl enable --now ove</pre>
|
|
|
741
754
|
|
|
742
755
|
<section class="section">
|
|
743
756
|
<h2>Commands</h2>
|
|
744
|
-
<p class="section-note">
|
|
757
|
+
<p class="section-note">Shortcuts for common tasks. You can also just type what you need in plain language.</p>
|
|
745
758
|
|
|
746
759
|
<dl class="cmd-grid">
|
|
747
760
|
<dt>review PR #N on <repo></dt>
|
|
@@ -782,7 +795,7 @@ sudo systemctl enable --now ove</pre>
|
|
|
782
795
|
<li><span class="step-n">2</span><span class="step-arrow">›</span> Router parses intent and extracts repo/args</li>
|
|
783
796
|
<li><span class="step-n">3</span><span class="step-arrow">›</span> Task gets queued in SQLite — one per repo at a time</li>
|
|
784
797
|
<li><span class="step-n">4</span><span class="step-arrow">›</span> Worker creates an isolated git worktree</li>
|
|
785
|
-
<li><span class="step-n">5</span><span class="step-arrow">›</span> Runs <code>claude -p</code> with streaming
|
|
798
|
+
<li><span class="step-n">5</span><span class="step-arrow">›</span> Runs the configured runner (<code>claude -p</code> or <code>codex exec</code>) with streaming JSON output</li>
|
|
786
799
|
<li><span class="step-n">6</span><span class="step-arrow">›</span> Status updates stream back — chat edits, SSE, or GitHub comment</li>
|
|
787
800
|
<li><span class="step-n">7</span><span class="step-arrow">›</span> Result sent back, worktree cleaned up</li>
|
|
788
801
|
</ol>
|
|
@@ -846,7 +859,7 @@ sudo systemctl enable --now ove</pre>
|
|
|
846
859
|
<p class="section-note">Pick your method. They all work. Ove doesn't care.</p>
|
|
847
860
|
|
|
848
861
|
<h3>Docker</h3>
|
|
849
|
-
<p>The Dockerfile builds an image with Bun, git, openssh-client, and Claude CLI baked in. Just mount your config and go.</p>
|
|
862
|
+
<p>The Dockerfile builds an image with Bun, git, openssh-client, and Claude CLI baked in. Install Codex CLI separately if needed. Just mount your config and go.</p>
|
|
850
863
|
<pre data-label="docker-compose.yml">services:
|
|
851
864
|
ove:
|
|
852
865
|
build: .
|
|
@@ -868,9 +881,12 @@ sudo systemctl enable --now ove</pre>
|
|
|
868
881
|
<pre data-label="shell"># Bun
|
|
869
882
|
curl -fsSL https://bun.sh/install | bash
|
|
870
883
|
|
|
871
|
-
# Claude Code
|
|
884
|
+
# Claude Code (default runner)
|
|
872
885
|
npm install -g @anthropic-ai/claude-code
|
|
873
886
|
|
|
887
|
+
# Or Codex CLI (alternative runner)
|
|
888
|
+
# npm install -g @openai/codex
|
|
889
|
+
|
|
874
890
|
# GitHub CLI
|
|
875
891
|
sudo apt install gh
|
|
876
892
|
gh auth login
|
|
@@ -915,7 +931,7 @@ journalctl -u ove -f</pre>
|
|
|
915
931
|
</div>
|
|
916
932
|
|
|
917
933
|
<footer>
|
|
918
|
-
Built by <a href="https://www.jacksoncage.se/">Love Billingskog Nyberg</a> · Powered by <a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code</a>
|
|
934
|
+
Built by <a href="https://www.jacksoncage.se/">Love Billingskog Nyberg</a> · Powered by <a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code</a> & <a href="https://github.com/openai/codex">Codex</a>
|
|
919
935
|
</footer>
|
|
920
936
|
|
|
921
937
|
</body>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Codex Runner Design
|
|
2
|
+
|
|
3
|
+
Add OpenAI Codex CLI as a second agent runner alongside Claude Code CLI.
|
|
4
|
+
|
|
5
|
+
## Config
|
|
6
|
+
|
|
7
|
+
Global default runner + per-repo override:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"runner": { "name": "claude" },
|
|
12
|
+
"repos": {
|
|
13
|
+
"my-app": {
|
|
14
|
+
"url": "git@github.com:user/my-app.git",
|
|
15
|
+
"defaultBranch": "main",
|
|
16
|
+
"runner": { "name": "codex", "model": "o3" }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`RunnerConfig`: `{ name: "claude" | "codex"; model?: string }`. Defaults to `"claude"` if omitted.
|
|
23
|
+
|
|
24
|
+
## New Types
|
|
25
|
+
|
|
26
|
+
`RunnerConfig` added to `config.ts` on both `Config` (global) and `RepoConfig` (per-repo). `RunOptions` gets optional `model` field.
|
|
27
|
+
|
|
28
|
+
## CodexRunner (`src/runners/codex.ts`)
|
|
29
|
+
|
|
30
|
+
Implements `AgentRunner`. Spawns `codex exec --json --yolo --skip-git-repo-check --ephemeral -C <workDir> "prompt"`.
|
|
31
|
+
|
|
32
|
+
Key differences from ClaudeRunner:
|
|
33
|
+
- No `--max-turns` (exec mode runs one turn, unlimited tool calls)
|
|
34
|
+
- No `--mcp-config` flag (Codex reads MCP from `~/.codex/config.toml`)
|
|
35
|
+
- JSONL output format (one JSON object per line) instead of Claude's stream-json
|
|
36
|
+
- Uses `CODEX_API_KEY` / `OPENAI_API_KEY` env vars
|
|
37
|
+
|
|
38
|
+
JSONL event mapping to `StatusEvent`:
|
|
39
|
+
- `item.completed` + `agent_message` -> `{ kind: "text" }` + final output
|
|
40
|
+
- `item.started` + `command_execution` -> `{ kind: "tool", tool: "shell" }`
|
|
41
|
+
- `item.started` + `file_change` -> `{ kind: "tool", tool: "file_change" }`
|
|
42
|
+
- `item.started` + `mcp_tool_call` -> `{ kind: "tool", tool: <name> }`
|
|
43
|
+
- `turn.failed` -> error output
|
|
44
|
+
|
|
45
|
+
## Runner Selection (`index.ts`)
|
|
46
|
+
|
|
47
|
+
Factory function creates runners by name. Per-task resolution: repo config -> global default -> "claude". Runners cached by name.
|
|
48
|
+
|
|
49
|
+
## Unchanged
|
|
50
|
+
|
|
51
|
+
`AgentRunner` interface, `RunResult`, `StatusEvent`, queue, router, adapters — all untouched.
|