@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 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, future Codex)
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
- ## Commands
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 NDJSON output
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
 
@@ -18,6 +18,9 @@
18
18
  "claude": {
19
19
  "maxTurns": 25
20
20
  },
21
+ "runner": {
22
+ "name": "claude"
23
+ },
21
24
  "mcpServers": {
22
25
  "filesystem": {
23
26
  "command": "npx",
package/docs/examples.md CHANGED
@@ -1,8 +1,56 @@
1
1
  # Example Interactions
2
2
 
3
- Examples showing Ove across different transports and command types.
3
+ Examples showing Ove across different transports. You can use shorthand commands or just chat naturally — Ove understands both.
4
4
 
5
- ## PR Review
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
- "Fine. I'll fix it. But I'm not happy about it."
597
- <span>— Ove, on every pull request</span>
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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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">Say what you need. Keep it simple. Ove doesn't do ambiguity.</p>
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 &lt;repo&gt;</dt>
@@ -782,7 +795,7 @@ sudo systemctl enable --now ove</pre>
782
795
  <li><span class="step-n">2</span><span class="step-arrow">&rsaquo;</span> Router parses intent and extracts repo/args</li>
783
796
  <li><span class="step-n">3</span><span class="step-arrow">&rsaquo;</span> Task gets queued in SQLite &mdash; one per repo at a time</li>
784
797
  <li><span class="step-n">4</span><span class="step-arrow">&rsaquo;</span> Worker creates an isolated git worktree</li>
785
- <li><span class="step-n">5</span><span class="step-arrow">&rsaquo;</span> Runs <code>claude -p</code> with streaming NDJSON output</li>
798
+ <li><span class="step-n">5</span><span class="step-arrow">&rsaquo;</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">&rsaquo;</span> Status updates stream back &mdash; chat edits, SSE, or GitHub comment</li>
787
800
  <li><span class="step-n">7</span><span class="step-arrow">&rsaquo;</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> &middot; 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> &middot; Powered by <a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code</a> &amp; <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.