Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,29 @@ jobs:
run: npm ci
- name: Tauri debug build
run: npm run tauri -- build --debug --no-bundle

build-windows:
runs-on: windows-latest
needs:
- lint
- typecheck
- test-js
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- uses: dtolnay/rust-toolchain@stable
- name: Install LLVM (bindgen)
run: choco install llvm -y --no-progress
- name: Configure LLVM (bindgen)
run: |
echo "LIBCLANG_PATH=C:\\Program Files\\LLVM\\bin" >> $env:GITHUB_ENV
echo "C:\\Program Files\\LLVM\\bin" >> $env:GITHUB_PATH
- name: Install dependencies
run: npm ci
- name: Doctor (Windows)
run: npm run doctor:win
- name: Tauri debug build (Windows)
run: npm run tauri -- build --debug --no-bundle --config src-tauri/tauri.windows.conf.json
91 changes: 91 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,74 @@ jobs:
name: appimage-${{ matrix.arch }}
path: src-tauri/target/release/bundle/appimage/*.AppImage*

build_windows:
runs-on: windows-latest
environment: release
env:
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
TAURI_SIGNING_PRIVATE_KEY_B64: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_B64 }}
steps:
- uses: actions/checkout@v4

- name: setup node
uses: actions/setup-node@v4
with:
node-version: lts/*
cache: npm

- name: install Rust stable
uses: dtolnay/rust-toolchain@stable

- name: Install LLVM (bindgen)
run: choco install llvm -y --no-progress

- name: Configure LLVM (bindgen)
run: |
echo "LIBCLANG_PATH=C:\\Program Files\\LLVM\\bin" >> $env:GITHUB_ENV
echo "C:\\Program Files\\LLVM\\bin" >> $env:GITHUB_PATH

- name: install frontend dependencies
run: npm ci

- name: Write Tauri signing key
shell: bash
run: |
set -euo pipefail
python - <<'PY'
import base64
import os
from pathlib import Path

raw = base64.b64decode(os.environ["TAURI_SIGNING_PRIVATE_KEY_B64"])
home = Path.home()
target = home / ".tauri"
target.mkdir(parents=True, exist_ok=True)
(target / "codexmonitor.key").write_bytes(raw)
PY

- name: build windows bundles
shell: bash
run: |
set -euo pipefail
export TAURI_SIGNING_PRIVATE_KEY
TAURI_SIGNING_PRIVATE_KEY="$(cat "$HOME/.tauri/codexmonitor.key")"
npm run tauri:build:win

- name: Upload Windows artifacts
uses: actions/upload-artifact@v4
with:
name: windows-artifacts
path: |
src-tauri/target/release/bundle/nsis/*.exe*
src-tauri/target/release/bundle/msi/*.msi*

release:
runs-on: ubuntu-latest
environment: release
needs:
- build_macos
- build_linux
- build_windows
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -244,6 +306,12 @@ jobs:
path: release-artifacts
merge-multiple: true

- name: Download Windows artifacts
uses: actions/download-artifact@v4
with:
name: windows-artifacts
path: release-artifacts

- name: Build latest.json
run: |
set -euo pipefail
Expand Down Expand Up @@ -345,6 +413,27 @@ jobs:
"signature": sig_path.read_text().strip(),
}

exe_candidates = sorted(artifacts_dir.rglob("*.exe"), key=lambda p: p.name.lower())
windows_installer = None
for candidate in exe_candidates:
lowered = candidate.name.lower()
if "setup" in lowered or "installer" in lowered:
windows_installer = candidate
break
if windows_installer is None and exe_candidates:
windows_installer = exe_candidates[0]
if windows_installer is None:
raise SystemExit("No Windows installer (.exe) found for latest.json")

win_sig_path = windows_installer.with_suffix(windows_installer.suffix + ".sig")
if not win_sig_path.exists():
raise SystemExit(f"Missing signature for {windows_installer.name}")

platforms["windows-x86_64"] = {
"url": f"https://github.com/Dimillian/CodexMonitor/releases/download/v${VERSION}/{windows_installer.name}",
"signature": win_sig_path.read_text().strip(),
}

payload = {
"version": "${VERSION}",
"notes": notes,
Expand Down Expand Up @@ -378,6 +467,8 @@ jobs:
release-artifacts/CodexMonitor.app.tar.gz \
release-artifacts/CodexMonitor.app.tar.gz.sig \
release-artifacts/*.AppImage* \
release-artifacts/*.exe* \
release-artifacts/*.msi* \
release-artifacts/latest.json

- name: Bump version and open PR
Expand Down
57 changes: 57 additions & 0 deletions PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Windows Support Execution Plan

Source of truth for requirements: `SPEC.md`.
This plan is **live** and tracks what has landed and what remains for the Windows milestone (auto-updater + dictation).

## Workstream

### 1) Docs

- [x] Add `SPEC.md` (Windows scope, updater + dictation required).
- [x] Keep `PLAN.md` current as work lands.

### 2) Git safety + PR

- [x] Push `feature/windows-support` to a fork remote and set upstream to avoid accidental `main` pushes.
- [x] Open a draft PR early so CI runs on every push.

### 3) Windows UX + path correctness

- [x] Make “Reveal in Finder” platform-aware (Explorer on Windows).
- [x] Fix path joining in the frontend so Windows absolute/relative paths behave.
- [x] Make backend `open_workspace_in` work cross-platform (macOS/Windows/Linux).
- [x] Make default “Open in” targets sensible on Windows (Explorer + command-based editors).

### 4) Dictation on Windows (required)

- [x] Enable Whisper dictation on Windows (`whisper-rs` + `cpal`) by removing the Windows stub.
- [x] Update Windows build checks (`doctor:win`) to require LLVM/Clang + CMake.
- [x] Fix `doctor:win` dependency detection on Unix (no shell builtins).

### 5) CI (required)

- [x] Add a Windows CI job that runs a Tauri debug build with `src-tauri/tauri.windows.conf.json`.

### 6) Release + updater (required)

- [x] Enable Windows updater artifacts in `src-tauri/tauri.windows.conf.json`.
- [x] Add a Windows release build job to `.github/workflows/release.yml`.
- [x] Extend `latest.json` generation to include Windows URL + signature.

## Validation (run after each step)

- `npm run lint`
- `npm run test`
- `npm run typecheck`
- Rust checks are executed in CI for macOS + Windows jobs added by this plan.

## Manual checklist (Windows)

- [ ] `npm run tauri:build:win` succeeds on Windows 10/11.
- [ ] App launches and can open workspaces.
- [ ] Adding a workspace succeeds when `codex --version` works in Windows Terminal.
- [ ] “Reveal in Explorer” opens the right folder.
- [ ] Shortcut hints use Ctrl/Alt labels and work on Windows.
- [ ] Theme dropdown options are readable in Dark/Dim with Reduce Transparency off.
- [ ] Auto-updater finds and applies the latest release.
- [ ] Dictation works end-to-end (download → hold-to-talk → transcript).
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![CodexMonitor](screenshot.png)

CodexMonitor is a macOS Tauri app for orchestrating multiple Codex agents across local workspaces. It provides a sidebar to manage projects, a home screen for quick actions, and a conversation view backed by the Codex app-server protocol.
CodexMonitor is a Tauri app for orchestrating multiple Codex agents across local workspaces. It provides a sidebar to manage projects, a home screen for quick actions, and a conversation view backed by the Codex app-server protocol.

## Features

Expand Down Expand Up @@ -46,7 +46,8 @@ CodexMonitor is a macOS Tauri app for orchestrating multiple Codex agents across

- Node.js + npm
- Rust toolchain (stable)
- CMake (required for native dependencies; Whisper/dictation uses it on non-Windows)
- CMake (required for native dependencies; dictation/Whisper uses it)
- LLVM/Clang (required on Windows to build dictation dependencies via bindgen)
- Codex installed on your system and available as `codex` in `PATH`
- Git CLI (used for worktree operations)
- GitHub CLI (`gh`) for the Issues panel (optional)
Expand Down Expand Up @@ -94,8 +95,8 @@ Artifacts will be in:

- `src-tauri/target/release/bundle/nsis/` (installer exe)
- `src-tauri/target/release/bundle/msi/` (msi)

Note: dictation is currently disabled on Windows builds (to avoid requiring LLVM/libclang for `whisper-rs`/bindgen).
Note: building from source on Windows requires LLVM/Clang (for `bindgen` / `libclang`) in addition to CMake.

## Type Checking

Expand Down
92 changes: 92 additions & 0 deletions SPEC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Windows Support Spec

## Goal

Ship a **fully functioning Windows version** of CodexMonitor with:

- **Auto-updater** enabled and wired into the release workflow (`latest.json` includes Windows).
- **Dictation** working on Windows (same UX + model management as other platforms).

This spec is the source of truth for Windows support requirements and acceptance criteria.

## Target Platforms

- Windows 10/11, **x86_64** (GitHub Actions `windows-latest`).

## Non-Goals (for this milestone)

- Authenticode / EV code signing (nice-to-have; not required to be functional).
- Windows ARM64 builds.

## Functional Requirements

### Updater (Required)

- Windows release artifacts must be produced by CI and attached to GitHub Releases.
- `latest.json` must include a **Windows platform entry** with:
- correct asset URL
- signature generated by Tauri updater signing
- In-app updater must be enabled for Windows builds (same endpoints + pubkey as other platforms).
- The updater entry for Windows uses the **NSIS installer** (`.exe` + `.exe.sig`) as the updater bundle.

### Dictation (Required)

Dictation must work on Windows with the same surface area as other platforms:

- Model status: missing/downloading/ready/error
- Model download/cancel/remove
- Session lifecycle: start/listening/stop->processing/transcript/cancel
- Emits the same Tauri events:
- `dictation-download`
- `dictation-event`

Implementation choice for this milestone:

- Use the existing Whisper-based implementation on Windows (via `whisper-rs` + `cpal`).

### Windows UX Correctness (Required)

- “Reveal in Finder” strings must be platform-aware (“Explorer” on Windows).
- Opening paths in an editor or file manager must behave correctly on Windows.
- Shortcut hints and formatting must be platform-aware on Windows (Ctrl/Alt labels; no macOS-only glyphs).
- Settings selects (for example Theme) must remain readable in Dark/Dim with Reduce Transparency off.

## Build & Tooling Requirements

### Windows Build Prereqs (dev + CI)

Required on Windows to build dictation (Whisper + bindgen):

- CMake
- LLVM/Clang (for `bindgen` / `libclang`)

`npm run doctor:win` must fail fast with actionable instructions if missing.
`npm run doctor:win` must correctly detect installed dependencies on Windows/macOS/Linux.

## CI / Release Requirements

### CI (Required)

- Add a Windows job to `.github/workflows/ci.yml` that:
- installs deps
- runs a Windows Tauri debug build (`--no-bundle`) using the Windows config

### Release (Required)

Update `.github/workflows/release.yml` to include Windows:

- Build Windows bundles on `windows-latest`
- Upload `.msi` / `.exe` plus updater `.sig` artifacts
- Include Windows in generated `latest.json`

## Acceptance Criteria

- `npm run tauri:build:win` succeeds on Windows.
- Windows release workflow publishes installers and `latest.json` that enables in-app updates.
- Dictation works on Windows end-to-end (model download → hold-to-talk → transcript).
- Adding a workspace works when `codex --version` runs in Windows Terminal (Codex PATH handling is correct).
- Repo checks pass:
- `npm run lint`
- `npm run test`
- `npm run typecheck`
- Rust checks executed in CI for Windows/macOS as configured
Loading