Skip to content

Commit 93406f6

Browse files
lidge-junclaude
andcommitted
feat(70): platform compat patches, install scripts, README platform table
- Windows taskkill for graceful process stop - PID EPERM handling for cross-user process checks - Cross-platform install scripts (install.sh + install.ps1) - README: supported platforms table, service manager details Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a9dd24f commit 93406f6

5 files changed

Lines changed: 70 additions & 3 deletions

File tree

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ Codex CLI / App / SDK ──/v1/responses──▶ opencodex ──▶ Any provi
3030
OpenRouter · Azure · DeepSeek · GLM · …and OpenAI itself
3131
```
3232

33+
## Supported platforms
34+
35+
| OS | Status | Service manager |
36+
|---|---|---|
37+
| macOS (arm64 / x64) | Fully supported | launchd |
38+
| Linux (x64 / arm64) | Fully supported | systemd (user unit) |
39+
| Windows (x64) | Fully supported | Task Scheduler |
40+
41+
Requires [Bun](https://bun.sh) 1.1+. All three platforms work natively (no WSL needed on Windows).
42+
3343
## Quick start
3444

3545
```bash
@@ -110,7 +120,7 @@ ocx status # is the proxy running?
110120
ocx login <xai|anthropic|kimi> # OAuth login
111121
ocx logout <provider> # remove a stored login
112122
ocx gui # open the web dashboard
113-
ocx service <install|start|stop|status|uninstall> # run as a background service
123+
ocx service <install|start|stop|status|uninstall> # background service (launchd/systemd/schtasks)
114124
ocx update # update opencodex to the latest published version
115125
```
116126

scripts/install.ps1

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#Requires -Version 5.1
2+
$ErrorActionPreference = "Stop"
3+
4+
Write-Host "Installing opencodex..." -ForegroundColor Cyan
5+
6+
# Check or install Bun
7+
if (-not (Get-Command bun -ErrorAction SilentlyContinue)) {
8+
Write-Host "Bun not found. Installing..."
9+
irm bun.sh/install.ps1 | iex
10+
$env:PATH = "$env:USERPROFILE\.bun\bin;$env:PATH"
11+
}
12+
13+
$bunVer = & bun --version
14+
Write-Host "Using Bun v$bunVer"
15+
16+
# Install opencodex globally
17+
& bun add -g @bitkyc08/opencodex
18+
19+
Write-Host ""
20+
Write-Host "opencodex installed! Run 'ocx init' to set up." -ForegroundColor Green

scripts/install.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
echo "Installing opencodex..."
5+
6+
# Check or install Bun
7+
if ! command -v bun &>/dev/null; then
8+
echo "Bun not found. Installing..."
9+
curl -fsSL https://bun.sh/install | bash
10+
export PATH="$HOME/.bun/bin:$PATH"
11+
fi
12+
13+
BUN_VER=$(bun --version)
14+
echo "Using Bun v$BUN_VER"
15+
16+
# Install opencodex globally
17+
bun add -g @bitkyc08/opencodex
18+
19+
echo ""
20+
echo "✅ opencodex installed! Run 'ocx init' to set up."

src/cli.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,22 @@ function handleStart() {
8484
process.on("SIGTERM", shutdown);
8585
}
8686

87+
function killProxy(pid: number): void {
88+
if (process.platform === "win32") {
89+
try {
90+
(require("node:child_process") as typeof import("node:child_process"))
91+
.execSync(`taskkill /PID ${pid} /T /F`, { stdio: "pipe" });
92+
} catch { /* process already gone */ }
93+
} else {
94+
process.kill(pid, "SIGTERM");
95+
}
96+
}
97+
8798
function handleStop() {
8899
const pid = readPid();
89100
if (pid) {
90101
try {
91-
process.kill(pid, "SIGTERM");
102+
killProxy(pid);
92103
console.log(`✅ Proxy (PID ${pid}) stopped.`);
93104
} catch {
94105
console.log("Proxy process not found.");

src/config.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,13 @@ export function readPid(): number | null {
9494
const raw = readFileSync(PID_PATH, "utf-8").trim();
9595
const pid = parseInt(raw, 10);
9696
if (isNaN(pid)) return null;
97-
try { process.kill(pid, 0); return pid; } catch { return null; }
97+
try {
98+
process.kill(pid, 0);
99+
return pid;
100+
} catch (e: unknown) {
101+
if ((e as NodeJS.ErrnoException).code === "EPERM") return pid;
102+
return null;
103+
}
98104
} catch {
99105
return null;
100106
}

0 commit comments

Comments
 (0)