@lovenyberg/ove 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/.dockerignore +7 -0
- package/.env.example +30 -0
- package/.github/workflows/ci.yml +16 -0
- package/.github/workflows/pages.yml +33 -0
- package/.github/workflows/publish.yml +45 -0
- package/CLAUDE.md +28 -0
- package/Dockerfile +37 -0
- package/LICENSE +21 -0
- package/README.md +183 -0
- package/bin/ove.ts +72 -0
- package/bun.lock +703 -0
- package/bunfig.toml +2 -0
- package/config.example.json +35 -0
- package/deploy/ove.service +15 -0
- package/docker-compose.yml +15 -0
- package/docs/CNAME +1 -0
- package/docs/examples.md +198 -0
- package/docs/index.html +922 -0
- package/docs/logo.png +0 -0
- package/logo.png +0 -0
- package/package.json +44 -0
- package/public/index.html +83 -0
- package/src/adapters/cli.ts +93 -0
- package/src/adapters/discord.test.ts +13 -0
- package/src/adapters/discord.ts +98 -0
- package/src/adapters/github.test.ts +21 -0
- package/src/adapters/github.ts +134 -0
- package/src/adapters/http.test.ts +87 -0
- package/src/adapters/http.ts +167 -0
- package/src/adapters/slack.ts +123 -0
- package/src/adapters/telegram.test.ts +15 -0
- package/src/adapters/telegram.ts +75 -0
- package/src/adapters/types.test.ts +38 -0
- package/src/adapters/types.ts +32 -0
- package/src/adapters/whatsapp.ts +118 -0
- package/src/adapters/wiring.test.ts +16 -0
- package/src/config.test.ts +51 -0
- package/src/config.ts +73 -0
- package/src/cron.test.ts +65 -0
- package/src/cron.ts +80 -0
- package/src/flows.test.ts +312 -0
- package/src/index.ts +588 -0
- package/src/logger.ts +29 -0
- package/src/queue.test.ts +113 -0
- package/src/queue.ts +131 -0
- package/src/repos.test.ts +31 -0
- package/src/repos.ts +81 -0
- package/src/router.test.ts +167 -0
- package/src/router.ts +125 -0
- package/src/runner.ts +21 -0
- package/src/runners/claude.test.ts +77 -0
- package/src/runners/claude.ts +107 -0
- package/src/schedule-flow.test.ts +67 -0
- package/src/schedule-parser.test.ts +37 -0
- package/src/schedule-parser.ts +70 -0
- package/src/schedules.test.ts +54 -0
- package/src/schedules.ts +73 -0
- package/src/sessions.test.ts +45 -0
- package/src/sessions.ts +55 -0
- package/src/setup.test.ts +195 -0
- package/src/setup.ts +248 -0
- package/src/smoke.test.ts +80 -0
- package/tsconfig.json +14 -0
package/.dockerignore
ADDED
package/.env.example
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Slack (Socket Mode)
|
|
2
|
+
SLACK_BOT_TOKEN=xoxb-...
|
|
3
|
+
SLACK_APP_TOKEN=xapp-...
|
|
4
|
+
|
|
5
|
+
# WhatsApp
|
|
6
|
+
WHATSAPP_ENABLED=false
|
|
7
|
+
|
|
8
|
+
# Telegram
|
|
9
|
+
# TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
|
|
10
|
+
|
|
11
|
+
# Discord
|
|
12
|
+
# DISCORD_BOT_TOKEN=MTIz...
|
|
13
|
+
|
|
14
|
+
# HTTP API + Web UI
|
|
15
|
+
# HTTP_API_PORT=3000
|
|
16
|
+
# HTTP_API_KEY=your-secret-key
|
|
17
|
+
|
|
18
|
+
# GitHub (polling for @mentions in issue/PR comments)
|
|
19
|
+
# GITHUB_POLL_REPOS=owner/repo1,owner/repo2
|
|
20
|
+
# GITHUB_BOT_NAME=ove
|
|
21
|
+
# GITHUB_POLL_INTERVAL=30000
|
|
22
|
+
|
|
23
|
+
# CLI mode (auto-enabled when no other adapters configured)
|
|
24
|
+
# CLI_MODE=true
|
|
25
|
+
|
|
26
|
+
# Repos directory
|
|
27
|
+
REPOS_DIR=./repos
|
|
28
|
+
|
|
29
|
+
# Config file path (optional, defaults to ./config.json)
|
|
30
|
+
# CONFIG_PATH=./config.json
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Deploy Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths: [docs/**]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: pages
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
deploy:
|
|
19
|
+
environment:
|
|
20
|
+
name: github-pages
|
|
21
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- uses: actions/configure-pages@v5
|
|
27
|
+
|
|
28
|
+
- uses: actions/upload-pages-artifact@v3
|
|
29
|
+
with:
|
|
30
|
+
path: docs
|
|
31
|
+
|
|
32
|
+
- id: deployment
|
|
33
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Publish Package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
packages: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: oven-sh/setup-bun@v2
|
|
17
|
+
- run: bun install
|
|
18
|
+
- run: bun test
|
|
19
|
+
|
|
20
|
+
publish:
|
|
21
|
+
needs: test
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- uses: actions/setup-node@v4
|
|
27
|
+
with:
|
|
28
|
+
node-version: 20
|
|
29
|
+
registry-url: https://registry.npmjs.org
|
|
30
|
+
|
|
31
|
+
- uses: oven-sh/setup-bun@v2
|
|
32
|
+
|
|
33
|
+
- run: bun install
|
|
34
|
+
|
|
35
|
+
# Update version from release tag (safe: GITHUB_REF_NAME is not user-controlled)
|
|
36
|
+
- name: Set version from tag
|
|
37
|
+
env:
|
|
38
|
+
REF_NAME: ${{ github.ref_name }}
|
|
39
|
+
run: |
|
|
40
|
+
VERSION="${REF_NAME#v}"
|
|
41
|
+
npm version "$VERSION" --no-git-tag-version --allow-same-version
|
|
42
|
+
|
|
43
|
+
- run: npm publish
|
|
44
|
+
env:
|
|
45
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Ove
|
|
2
|
+
|
|
3
|
+
Your grumpy but meticulous dev companion — routes chat messages to Claude Code CLI in isolated worktrees.
|
|
4
|
+
|
|
5
|
+
## Stack
|
|
6
|
+
- Bun + TypeScript
|
|
7
|
+
- @slack/bolt (Socket Mode) for Slack
|
|
8
|
+
- baileys for WhatsApp
|
|
9
|
+
- grammy for Telegram
|
|
10
|
+
- discord.js for Discord
|
|
11
|
+
- Bun.serve for HTTP API + Web UI
|
|
12
|
+
- gh CLI for GitHub polling
|
|
13
|
+
- bun:sqlite for task queue
|
|
14
|
+
- claude -p CLI for code tasks
|
|
15
|
+
|
|
16
|
+
## Structure
|
|
17
|
+
- src/adapters/ — chat platform adapters (Slack, WhatsApp, Telegram, Discord, CLI) and event adapters (GitHub, HTTP API)
|
|
18
|
+
- src/queue.ts — SQLite task queue
|
|
19
|
+
- src/runners/ — agent runner implementations (Claude, future Codex)
|
|
20
|
+
- src/repos.ts — git clone/pull/worktree management
|
|
21
|
+
- src/router.ts — message → task mapping
|
|
22
|
+
- src/config.ts — repo/user configuration
|
|
23
|
+
|
|
24
|
+
## Conventions
|
|
25
|
+
- No classes unless necessary, prefer functions and plain objects
|
|
26
|
+
- Use bun:sqlite directly, no ORMs
|
|
27
|
+
- Use bun:test for testing
|
|
28
|
+
- Structured JSON logging via src/logger.ts
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
FROM oven/bun:1 AS base
|
|
2
|
+
|
|
3
|
+
# System deps: git for repo management, ssh for private repos
|
|
4
|
+
RUN apt-get update && \
|
|
5
|
+
apt-get install -y --no-install-recommends git openssh-client && \
|
|
6
|
+
rm -rf /var/lib/apt/lists/*
|
|
7
|
+
|
|
8
|
+
# Claude CLI (installed via npm since bun global install has quirks)
|
|
9
|
+
RUN bunx --bun npm i -g @anthropic-ai/claude-code
|
|
10
|
+
|
|
11
|
+
WORKDIR /app
|
|
12
|
+
|
|
13
|
+
# Install dependencies
|
|
14
|
+
COPY package.json bun.lock ./
|
|
15
|
+
RUN bun install --frozen-lockfile --production
|
|
16
|
+
|
|
17
|
+
# Copy source
|
|
18
|
+
COPY bin/ bin/
|
|
19
|
+
COPY src/ src/
|
|
20
|
+
COPY tsconfig.json ./
|
|
21
|
+
COPY config.example.json .env.example ./
|
|
22
|
+
|
|
23
|
+
# Non-root user (Claude CLI refuses --dangerously-skip-permissions as root)
|
|
24
|
+
# Default UID/GID 1000 matches most host users; override with --build-arg
|
|
25
|
+
ARG UID=1000
|
|
26
|
+
ARG GID=1000
|
|
27
|
+
RUN groupadd -g $GID ove 2>/dev/null || true && \
|
|
28
|
+
useradd -m -s /bin/bash -u $UID -g $GID ove 2>/dev/null || true && \
|
|
29
|
+
mkdir -p repos && \
|
|
30
|
+
chown -R $UID:$GID /app
|
|
31
|
+
USER $UID
|
|
32
|
+
|
|
33
|
+
# Git safe.directory for mounted volumes
|
|
34
|
+
RUN git config --global --add safe.directory '*'
|
|
35
|
+
|
|
36
|
+
ENTRYPOINT ["bun", "run", "bin/ove.ts"]
|
|
37
|
+
CMD ["start"]
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Love Nyberg
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="logo.png" width="180" alt="Ove" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Ove</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
Your grumpy but meticulous dev companion.<br>
|
|
9
|
+
<a href="https://jacksoncage.github.io/ove">Docs</a> · <a href="https://github.com/jacksoncage/ove">GitHub</a> · <a href="https://github.com/jacksoncage/ove/pkgs/npm/ove">Package</a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
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
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g @jacksoncage/ove
|
|
20
|
+
ove init # interactive setup — creates config.json and .env
|
|
21
|
+
ove start
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Prerequisites
|
|
25
|
+
|
|
26
|
+
- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated
|
|
27
|
+
- [GitHub CLI](https://cli.github.com) (`gh`) installed and authenticated
|
|
28
|
+
- SSH access to your git repos
|
|
29
|
+
|
|
30
|
+
## Commands
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
review PR #N on <repo> Code review with inline comments
|
|
34
|
+
fix issue #N on <repo> Read issue, implement fix, create PR
|
|
35
|
+
simplify <path> in <repo> Reduce complexity, create PR
|
|
36
|
+
validate <repo> Run tests and linter
|
|
37
|
+
discuss <topic> Brainstorm ideas (no code changes)
|
|
38
|
+
create project <name> Scaffold a new project
|
|
39
|
+
|
|
40
|
+
Scheduling:
|
|
41
|
+
<task> every day at <time> Schedule a recurring task
|
|
42
|
+
list schedules See your scheduled tasks
|
|
43
|
+
remove schedule #N Remove a scheduled task
|
|
44
|
+
|
|
45
|
+
Meta:
|
|
46
|
+
status Queue stats
|
|
47
|
+
history Recent tasks
|
|
48
|
+
clear Reset conversation
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Deployment
|
|
52
|
+
|
|
53
|
+
Three ways to run Ove. Pick what fits. See the [full guide](https://jacksoncage.github.io/ove#getting-started) for details.
|
|
54
|
+
|
|
55
|
+
### Local
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g @jacksoncage/ove
|
|
59
|
+
ove init
|
|
60
|
+
ove start
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Requires [Bun](https://bun.sh), Claude Code CLI, and GitHub CLI on your machine.
|
|
64
|
+
|
|
65
|
+
### Docker
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
ove init # generate config locally
|
|
69
|
+
docker compose up -d # start container
|
|
70
|
+
docker compose logs -f # watch logs
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The image includes Bun, git, and Claude CLI. Mounts `config.json`, `.env`, `repos/`, and SSH keys from the host.
|
|
74
|
+
|
|
75
|
+
### VM
|
|
76
|
+
|
|
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:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
git clone git@github.com:jacksoncage/ove.git && cd ove
|
|
81
|
+
bun install
|
|
82
|
+
ove init
|
|
83
|
+
sudo cp deploy/ove.service /etc/systemd/system/ove.service
|
|
84
|
+
sudo systemctl enable --now ove
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Transport Setup
|
|
88
|
+
|
|
89
|
+
### Slack
|
|
90
|
+
|
|
91
|
+
1. Create app at [api.slack.com/apps](https://api.slack.com/apps)
|
|
92
|
+
2. Enable **Socket Mode** → generate App-Level Token (`xapp-...`)
|
|
93
|
+
3. Bot scopes: `chat:write`, `channels:history`, `groups:history`, `im:history`, `mpim:history`, `app_mentions:read`
|
|
94
|
+
4. Event subscriptions: `message.im`, `app_mention`
|
|
95
|
+
5. **App Home** → Messages Tab → "Allow users to send messages"
|
|
96
|
+
6. Install to workspace → copy Bot Token (`xoxb-...`)
|
|
97
|
+
|
|
98
|
+
### Telegram
|
|
99
|
+
|
|
100
|
+
1. Message [@BotFather](https://t.me/BotFather) → `/newbot`
|
|
101
|
+
2. Copy the bot token
|
|
102
|
+
3. Set `TELEGRAM_BOT_TOKEN=<token>` in `.env`
|
|
103
|
+
|
|
104
|
+
### Discord
|
|
105
|
+
|
|
106
|
+
1. Create app at [discord.com/developers](https://discord.com/developers/applications)
|
|
107
|
+
2. Bot → enable **Message Content Intent**
|
|
108
|
+
3. Copy bot token
|
|
109
|
+
4. Invite bot to server with `bot` scope + `Send Messages`, `Read Message History`
|
|
110
|
+
5. Set `DISCORD_BOT_TOKEN=<token>` in `.env`
|
|
111
|
+
|
|
112
|
+
### HTTP API + Web UI
|
|
113
|
+
|
|
114
|
+
1. Set `HTTP_API_PORT=3000` and `HTTP_API_KEY=<your-secret>` in `.env`
|
|
115
|
+
2. Open `http://localhost:3000` for the Web UI
|
|
116
|
+
3. Or call the API directly: `curl -X POST http://localhost:3000/api/message -H "X-API-Key: <key>" -H "Content-Type: application/json" -d '{"text": "validate my-app"}'`
|
|
117
|
+
|
|
118
|
+
### GitHub (issue/PR comments)
|
|
119
|
+
|
|
120
|
+
1. Set `GITHUB_POLL_REPOS=owner/repo1,owner/repo2` in `.env`
|
|
121
|
+
2. Optionally set `GITHUB_BOT_NAME=ove` (default) and `GITHUB_POLL_INTERVAL=30000`
|
|
122
|
+
3. Mention `@ove` in an issue or PR comment to trigger a task
|
|
123
|
+
4. Ove replies with a comment when the task completes
|
|
124
|
+
|
|
125
|
+
### WhatsApp
|
|
126
|
+
|
|
127
|
+
1. Set `WHATSAPP_ENABLED=true` in `.env`
|
|
128
|
+
2. Scan the QR code printed in the terminal on first start
|
|
129
|
+
|
|
130
|
+
## Config
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"repos": {
|
|
135
|
+
"my-app": {
|
|
136
|
+
"url": "git@github.com:org/my-app.git",
|
|
137
|
+
"defaultBranch": "main"
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"users": {
|
|
141
|
+
"slack:U0ABC1234": { "name": "alice", "repos": ["my-app"] },
|
|
142
|
+
"telegram:123456789": { "name": "alice", "repos": ["my-app"] },
|
|
143
|
+
"discord:987654321": { "name": "alice", "repos": ["my-app"] },
|
|
144
|
+
"github:alice": { "name": "alice", "repos": ["my-app"] },
|
|
145
|
+
"http:anon": { "name": "alice", "repos": ["my-app"] },
|
|
146
|
+
"cli:local": { "name": "alice", "repos": ["my-app"] }
|
|
147
|
+
},
|
|
148
|
+
"claude": { "maxTurns": 10 },
|
|
149
|
+
"cron": [
|
|
150
|
+
{
|
|
151
|
+
"schedule": "0 9 * * 1-5",
|
|
152
|
+
"repo": "my-app",
|
|
153
|
+
"prompt": "Run lint and tests.",
|
|
154
|
+
"userId": "slack:U0ABC1234"
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
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
|
+
|
|
162
|
+
## Testing
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
bun test # 150 tests
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## How It Works
|
|
169
|
+
|
|
170
|
+
1. Message arrives via any transport (Slack, WhatsApp, Telegram, Discord, CLI, HTTP API, or GitHub comment)
|
|
171
|
+
2. Chat adapters use `handleMessage`, event adapters use `handleEvent`
|
|
172
|
+
3. Router parses intent and extracts repo/args
|
|
173
|
+
4. Task gets queued in SQLite (one per repo at a time)
|
|
174
|
+
5. Worker creates an isolated git worktree
|
|
175
|
+
6. Runs `claude -p` with streaming NDJSON output
|
|
176
|
+
7. Status updates stream back (chat: edits a message, HTTP: SSE, GitHub: single comment)
|
|
177
|
+
8. Result sent back, worktree cleaned up
|
|
178
|
+
|
|
179
|
+
See [example conversations](docs/examples.md) for all flows.
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
MIT
|
package/bin/ove.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { createInterface } from "node:readline/promises";
|
|
6
|
+
import { validateConfig, runSetup } from "../src/setup";
|
|
7
|
+
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
const command = args[0];
|
|
10
|
+
|
|
11
|
+
if (command === "init") {
|
|
12
|
+
if (existsSync("config.json")) {
|
|
13
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
14
|
+
const answer = await rl.question(" Config already exists. Overwrite? (y/n): ");
|
|
15
|
+
rl.close();
|
|
16
|
+
if (answer.trim().toLowerCase() !== "y") {
|
|
17
|
+
console.log(" Aborted.");
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
await runSetup();
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (command === "start" || !command) {
|
|
26
|
+
process.stdout.write("\n Checking config...\n");
|
|
27
|
+
const { valid, issues } = validateConfig();
|
|
28
|
+
|
|
29
|
+
if (!valid) {
|
|
30
|
+
for (const issue of issues) {
|
|
31
|
+
process.stdout.write(` ⚠ ${issue}\n`);
|
|
32
|
+
}
|
|
33
|
+
process.stdout.write("\n");
|
|
34
|
+
|
|
35
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
36
|
+
const answer = await rl.question(" Want to fix these now? (y/n): ");
|
|
37
|
+
rl.close();
|
|
38
|
+
|
|
39
|
+
if (answer.trim().toLowerCase() === "y") {
|
|
40
|
+
await runSetup({ fixOnly: issues });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
process.stdout.write(" Starting Ove...\n\n");
|
|
45
|
+
const entry = join(import.meta.dir, "..", "src", "index.ts");
|
|
46
|
+
await import(entry);
|
|
47
|
+
} else if (command === "test") {
|
|
48
|
+
console.log("Run: bun test");
|
|
49
|
+
process.exit(0);
|
|
50
|
+
} else if (command === "help" || command === "--help" || command === "-h") {
|
|
51
|
+
console.log(`
|
|
52
|
+
ove - Your grumpy but meticulous dev companion
|
|
53
|
+
|
|
54
|
+
Usage:
|
|
55
|
+
ove Start Ove (auto-detects Slack/CLI from env)
|
|
56
|
+
ove start Same as above
|
|
57
|
+
ove init Interactive setup — creates config.json and .env
|
|
58
|
+
ove help Show this message
|
|
59
|
+
|
|
60
|
+
Environment:
|
|
61
|
+
SLACK_BOT_TOKEN Slack bot token (xoxb-...)
|
|
62
|
+
SLACK_APP_TOKEN Slack app token (xapp-...)
|
|
63
|
+
CLI_MODE=true Force CLI mode
|
|
64
|
+
REPOS_DIR Directory for git repos (default: ./repos)
|
|
65
|
+
|
|
66
|
+
More info: https://jacksoncage.github.io/ove
|
|
67
|
+
`);
|
|
68
|
+
process.exit(0);
|
|
69
|
+
} else {
|
|
70
|
+
console.log(`Unknown command: ${command}. Run 'ove help' for usage.`);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|