Mohamed BoudraGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
7c50b7a080 fix(server): harden Codex/Windows startup and provider resolution (#454)
* fix(server): harden Codex/Windows startup and provider resolution

Addresses #452, #443, #353, #418, #403, #221, #307, and locks in #284.

- Replace custom where.exe/which output parsing with npm `which@^5` plus a
  spawn probe. findExecutable now enumerates all PATH+PATHEXT candidates
  and returns the first invokable one. A WindowsApps-ACL'd codex.exe no
  longer wins over a working codex.cmd (#452).
- Make default provider isAvailable() check the binary instead of always
  returning true. Codex/Claude/OpenCode default isAvailable() now defer
  to isCommandAvailable() so missing CLIs surface as unavailable instead
  of throwing later from spawn (#221, #443).
- Gate AgentManager.resumeAgentFromPersistence on isAvailable() so a
  persisted agent record with a missing binary cannot reach provider
  spawn during rehydration. The daemon stays up and the agent reports
  unavailable (#443, #353, #418, #403).
- Drop --path-format=absolute from rev-parse callers and validate stdout
  through a shared parser that rejects multi-line output and unknown-flag
  echoes. --show-toplevel is absolute by default in modern Git;
  --git-common-dir is resolved against the command cwd. Fixes workspace
  registration on pre-2.31 Git that echoed the unknown flag and produced
  a two-line "path" (#307).

Tests:
- Real-FS executable.test.ts using temp PATH fixtures, covering the .cmd
  fallback after .exe pre-spawn failure (Windows-only) plus the
  null-on-no-invokable-candidate case.
- provider-availability.test.ts builds real provider clients against a
  temp-dir-only PATH for Codex/Claude/OpenCode.
- bootstrap-provider-availability.test.ts builds the daemon and triggers
  ensureAgentLoaded so it actually exercises resumeAgentFromPersistence.
- claude-agent.spawn.test.ts asserts shell: false reaches spawnProcess
  from the Claude SDK spawn override, locking in 39b56af4 for #284.
- checkout-git-rev-parse.test.ts covers nested-checkout resolution and
  the old-Git multi-line stdout case via a tightly-scoped runGitCommand
  fake.

CI:
- server-tests-windows now also runs the new and modified test files so
  the Windows behaviors are exercised on windows-latest.

* fix: update lockfile signatures and Nix hash

* fix(server): handle synchronous spawn UNKNOWN on Windows

On Windows, child_process.spawn() throws synchronously when invoked on
a corrupt or invalid .exe (e.g., a WindowsApps stub the current user
cannot execute, or a zero-byte file). The executable probe did not
guard the spawn call, so the synchronous throw rejected the probe
promise instead of resolving false, preventing findExecutable() from
trying the next candidate. This is the root cause of the daemon-crash
pattern in #452: codex.exe from WindowsApps would hard-fail before the
.cmd shim ever got a chance.

Wrap spawn() in try/catch and settle false on sync throw. The existing
error-event and exit-event handlers already cover async failure modes;
sync throw just needed one more guard.

Also adjust three Windows-only test comparisons that were asserting
platform-dependent string equality:
- executable.test: compare .cmd paths case-insensitively (which@5
  preserves PATHEXT casing, which is uppercase in production).
- workspace-registry-model.test: expect normalizeWorkspaceId(path),
  not the hardcoded POSIX form.
- checkout-git-rev-parse.test: normalize separators/case when
  comparing git's Windows forward-slash output against realpathSync.

* test(server): canonicalize repo root via git on Windows to fix short-name mismatch

realpathSync on Windows preserves 8.3 short names (e.g. RUNNER~1) while git's
rev-parse --show-toplevel always returns the long-name form (runneradmin).
Use git as the canonicalizer on both sides of the assertion so the comparison
holds regardless of how Windows exposes the temp directory path.

* fix(server): Claude is always available in default mode; SDK bundles cli.js

The Phase 2 change wrongly tied Claude's default-mode isAvailable() to
isCommandAvailable("claude"). Claude's default runtime does not use an
external `claude` binary — @anthropic-ai/claude-agent-sdk ships its own
cli.js and spawnClaudeCodeProcess runs it via process.execPath. The
previous `return true` was correct; restore it.

Update provider-availability.test.ts to assert the truthful behavior:
Claude reports available even when no `claude` binary is on PATH.

Codex and OpenCode genuinely require their binaries on PATH, so their
availability checks remain unchanged.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-04-16 16:36:13 +08:00
2026-03-06 16:49:40 +01:00
2026-03-06 16:49:40 +01:00
2026-04-14 21:17:12 +07:00
2026-03-25 23:42:44 +07:00
2026-02-25 13:53:23 +07:00
2026-04-15 21:02:07 +07:00
2026-04-10 22:49:25 +07:00

Paseo logo

Paseo

GitHub stars GitHub release X Discord

One interface for all your Claude Code, Codex and OpenCode agents.

Paseo app screenshot

Paseo mobile app


Run agents in parallel on your own machines. Ship from your phone or your desk.

  • Self-hosted: Agents run on your machine with your full dev environment. Use your tools, your configs, and your skills.
  • Multi-provider: Claude Code, Codex, and OpenCode through the same interface. Pick the right model for each job.
  • Voice control: Dictate tasks or talk through problems in voice mode. Hands-free when you need it.
  • Cross-device: iOS, Android, desktop, web, and CLI. Start work at your desk, check in from your phone, script it from the terminal.
  • Privacy-first: Paseo doesn't have any telemetry, tracking, or forced log-ins.

Getting Started

Paseo runs a local server called the daemon that manages your coding agents. Clients like the desktop app, mobile app, web app, and CLI connect to it.

Prerequisites

You need at least one agent CLI installed and configured with your credentials:

Download it from paseo.sh/download or the GitHub releases page. Open the app and the daemon starts automatically. Nothing else to install.

To connect from your phone, scan the QR code shown in Settings.

CLI / headless

Install the CLI and start Paseo:

npm install -g @getpaseo/cli
paseo

This shows a QR code in the terminal. Connect from any client. This path is useful for servers and remote machines.

For full setup and configuration, see:

CLI

Everything you can do in the app, you can do from the terminal.

paseo run --provider claude/opus-4.6 "implement user authentication"
paseo run --provider codex/gpt-5.4 --worktree feature-x "implement feature X"

paseo ls                           # list running agents
paseo attach abc123                # stream live output
paseo send abc123 "also add tests" # follow-up task

# run on a remote daemon
paseo --host workstation.local:6767 run "run the full test suite"

See the full CLI reference for more.

Orchestration skills (Unstable)

Experimental skills that teach agents how to use the Paseo CLI to orchestrate other agents. I am updating these very frequently as I learn new things, expect changes without notice, might be coupled to my own setup, use at your own risk.

npx skills add getpaseo/paseo

Then use them in any agent conversation:

# Use handoff when you discuss something with an agent but want another one to implement.
# I use this to plan with Claude and then handoff to Codex to implement.
/paseo-handoff hand off the authentication fix to codex 5.4 in a worktree

# Use loops when you have clear acceptance criteria (aka Ralph loops).
/paseo-loop loop a codex agent to fix the backend tests, use sonnet to verify, max 10 iterations

# Orchestrator teaches the agent how to create teams and manage them via a chat room.
# Very opinionated and expects both Codex and Claude to work.
/paseo-orchestrator spin up a team to implement the database refactor, use chat to coordinate. use claude to plan and codex to implement and review

Development

Quick monorepo package map:

  • packages/server: Paseo daemon (agent process orchestration, WebSocket API, MCP server)
  • packages/app: Expo client (iOS, Android, web)
  • packages/cli: paseo CLI for daemon and agent workflows
  • packages/desktop: Electron desktop app
  • packages/relay: Relay package for remote connectivity
  • packages/website: Marketing site and documentation (paseo.sh)

Common commands:

# run all local dev services
npm run dev

# run individual surfaces
npm run dev:server
npm run dev:app
npm run dev:desktop
npm run dev:website

# build the daemon
npm run build:daemon

# repo-wide checks
npm run typecheck

License

AGPL-3.0

S
Description
No description provided
Readme AGPL-3.0
111 MiB
Languages
TypeScript 98%
JavaScript 1.4%
Shell 0.1%