Mohamed BoudraandGitHub 72b67f48e3 Eliminate spiky terminal lag under load (#1500)
* Eliminate spiky terminal lag under load

Terminal output stuttered during heavy output and when the daemon was
busy. Two compounding causes, both confirmed by measurement:

- Every 256KB of output, the daemon dropped pending frames and re-sent a
  full cell-grid snapshot (cloned across IPC, stringified to JSON) — a
  10MB build did this ~40 times. The snapshot fallback is now gated on
  real client backpressure (ws bufferedAmount), so a client that keeps
  draining streams continuously and never pays the snapshot tax. This
  also removes the periodic GC hitch the churn caused.
- Per-chunk overhead on the shared event loop: one IPC message per pty
  chunk, a duplicate input-mode regex scan on the daemon main loop, a
  double JSON.stringify per outbound message, and 16KB string realloc
  per chunk. Output now coalesces in the worker before IPC (leading-edge
  so keystrokes still echo immediately), the duplicate scan is gone, and
  the client feeds xterm back-to-back instead of one render tick a frame.

Adds eventLoopDelay percentiles to ws_runtime_metrics for main-loop
stall visibility, plus a reproducible Node benchmark (no port 6767).

Measured: echo p50 7.7ms to 2.3ms; a 2MB burst now streams fully with
zero snapshots; loop-stall spikes 100-173ms to 2ms.

* Guard trace-level check against partial logger stubs

The isLevelEnabled gate added for the emit() perf fix crashed every
session test that injects a hand-rolled logger stub (10 of them omit
isLevelEnabled). Real pino loggers always provide it; optional-chaining
keeps the perf gate intact in production and no-ops on stubs.

* Make recent-output exit-summary test deterministic

The added test self-exited the child immediately after writing 3000
lines, then asserted the newest line was in the exit summary — but the
summary reads the headless xterm buffer, which parses writes
asynchronously, so a loaded CI runner saw a stale buffer (line-2707 not
line-2999). Keep the process alive and poll the parsed buffer until the
final line lands before killing, removing the race.

* Skip ConPTY-fragile worker terminal tests on Windows

The coalescing and input-mode-preamble tests assert byte-contiguous PTY
output and an exact kitty-escape round-trip. Windows ConPTY injects
repaint sequences between writes and normalizes the escape, so both time
out there while passing on Linux/macOS. Gate them with skipIf(win32),
matching the existing terminal-test convention for PTY-sensitive cases.

* Apply terminal barriers immediately when no writes are pending

A barrier op (snapshot/restore/clear) only needs the sentinel-write gate
to wait out plain writes still parsing in xterm's buffer. When none are
ungated — at mount, or right after another barrier — the sentinel cost a
wasted parse cycle, adding latency to the first snapshot/restore on the
hot first-paint path. Track ungated writes with a flag and skip the
sentinel when there's nothing to gate.

* Fix mobile startup saved-host e2e

* Unskip Windows worker terminal coverage

* Tighten worker coalescing assertion

* Reset terminal ungated writes on unmount

* Fix terminal regressions found in adversarial review

Three issues this PR's terminal changes introduced:

- Worker snapshot could duplicate coalesced output. getTerminalState
  snapshotted without flushing the worker output coalescer, so a batch
  spanning the snapshot point carried a revision past it and the
  controller's dedup couldn't drop it — the client saw the bytes twice.
  Flush before snapshotting.
- Relay clients lost backpressure protection. The snapshot fallback was
  gated on bufferedAmount, which the multiplexed relay socket reports as
  absent; that read as 0 ("keeping up") so a slow relay client never
  caught up via a snapshot. Distinguish "no signal" (null) from 0 and
  keep the unconditional byte-threshold fallback for signal-less
  transports, preserving the pre-change relay behavior.
- Recent-output buffer was no longer a hard cap. A single chunk larger
  than the limit was retained whole; slice its tail.

Documents the live-restore preamble gap (unreachable: no client sends
restore mode "live").

* Skip input-mode preamble test on Windows ConPTY

CI confirmed Windows ConPTY normalizes away the kitty keyboard escape
the child writes, so it never reaches the worker's input-mode tracker
and the preamble stays empty — the test times out. ConPTY can't exercise
this contract; the coalescing test (file-gated, line-oriented) stays on
all platforms, only the preamble assertion is gated to Linux/macOS.
2026-06-13 05:38:58 +00:00
2026-06-05 22:30:53 +07:00
2026-06-07 23:18:32 +07:00
2026-03-06 16:49:40 +01:00
2026-03-06 16:49:40 +01:00
2026-06-13 08:45:21 +07:00
2026-05-15 00:09:52 +08:00
2026-02-25 13:53:23 +07:00
2026-06-13 08:46:33 +07:00

Paseo logo

Paseo

English · 简体中文

GitHub stars GitHub release X Discord Reddit

One interface for Claude Code, Codex, Copilot, OpenCode, and Pi agents.

Paseo app screenshot

Paseo mobile app

Note

I'm a solo maintainer and don't always keep up with GitHub Issues daily. If something is urgent or blocking you, Discord is the fastest place to reach me.


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, Copilot, OpenCode, and Pi 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.

Skills

Skills teach your agent to use Paseo to orchestrate other agents.

npx skills add getpaseo/paseo

Then use them in any agent conversation:

  • /paseo-handoff — hand off work between agents. I use this to plan with Claude and then handoff to Codex to implement.
  • /paseo-loop — loop an agent against clear acceptance criteria (aka Ralph loops), optionally with a verifier.
  • /paseo-advisor — spin up a single agent as an advisor for a second opinion, without delegating the work itself.
  • /paseo-committee — form a committee of two contrasting agents to step back, do root cause analysis, and produce a plan.

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 server stack
npm run build:server

# repo-wide checks
npm run typecheck

Community


Star history chart for getpaseo/paseo

License

AGPL-3.0

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