gate4agent
Universal Rust transport library for CLI AI agents. Spawn, stream, resume — for five different CLI agents through one unified API.
Not a harness. Not a sandbox. gate4agent is the thin wiring layer between your Rust app and the CLI agent's subprocess: spawn the binary, write the prompt, read structured events, resume by session id. That's it.
Supported CLI tools
| Tool | Transport | Pipe mode | Resume | Notes |
|---|---|---|---|---|
| Claude Code | Pipe + PTY | ✓ stream-json | ✓ --resume <id> |
Prompt via stdin |
| Codex | Pipe + PTY | ✓ --json |
✓ exec resume <id> |
Requires --ask-for-approval never --skip-git-repo-check |
| Gemini | Pipe + PTY | ✓ stream-json | ✓ --resume <id> |
Prompt via -p flag |
| Cursor Agent | Pipe | ✓ stream-json | ✓ --resume <id> |
Claude-compatible schema |
OpenCode (sst/opencode) |
Pipe | ✓ --format json |
✓ --session ses_XXX |
5-event NDJSON schema |
Transport classes:
- Pipe: spawn the CLI directly, read NDJSON over stdout
- PTY: spawn inside a pseudo-terminal, scrape the screen with vt100 (for agents without structured output)
Quick start
use ;
use PathBuf;
async
Resume an existing session
let opts = SpawnOptions ;
Each CLI handles resume in its own way — Codex swaps exec → exec resume <id>, Claude/Cursor use --resume <id>, OpenCode uses --session <ses_XXX>. gate4agent hides the difference behind SpawnOptions::resume_session_id.
Using PipeSession directly (backwards-compatible API)
use ;
let config = SessionConfig ;
let opts = PipeProcessOptions ;
let session = spawn.await?;
Features
- Single API for 5 CLIs —
TransportSession::spawn(tool, cwd, prompt, options) - Backwards-compatible
PipeSession— 0.1.x consumers that usedPipeSession::spawn(config, prompt, options)compile unchanged - SessionEnd synthesis — Codex has no terminal event; gate4agent synthesizes
SessionEnd { result: "exit_code=N", is_error: N != 0 }on child exit - Transport-neutral events —
AgentEvent::{Text, ToolStart, ToolResult, Thinking, TurnComplete, SessionStart, SessionEnd} - Cross-platform — Windows (ConPTY +
cmd /Cargv wrapping) and Unix (POSIX PTY + bare exec) - Rate-limit detection — pattern-based session/daily/weekly limit detection per CLI
- Zero new dependencies — gate4agent 0.2.1 removes dead fantasy transports without adding anything new
Architecture
gate4agent/
├── src/
│ ├── lib.rs — Library root, re-exports
│ ├── core/ — AgentEvent, CliTool, SessionConfig, AgentError
│ ├── transport/ — TransportSession (thin router over PipeSession), SpawnOptions
│ ├── pipe/ — PipeSession, PipeProcess, per-CLI NDJSON parsers + command builders
│ │ └── cli/ — claude.rs, codex.rs, gemini.rs, cursor.rs, opencode.rs
│ ├── pty/ — PtyWrapper, PtySession, VTE/screen parsers, per-CLI PTY parsers
│ │ └── cli/ — Per-CLI PTY output parsers
│ ├── history/ — Session history reader
│ └── utils.rs — String utilities
Testing status
| Tool | Pipe tested? | PTY tested? | Notes |
|---|---|---|---|
| Claude Code | ✓ verified in 0.1.x | ✗ untested | Primary consumer, production-proven pipe |
| Codex | ✗ research-based | ✗ untested | Parser from OpenAI docs, not live-verified |
| Gemini | ✗ research-based | ✗ untested | Parser from Google docs, not live-verified |
| Cursor Agent | ✗ research-based | N/A (no PTY) | Closed-source CLI, community-sourced field names |
| OpenCode | ✗ research-based | ✗ untested | Parser from sst/opencode source, not live-verified |
PTY parsers existed in 0.1.x and are structurally simple (screen scraping) — low risk of breakage. New pipe parsers (0.2.3) are backed by unit tests with fixture JSON but have NOT been tested against actual CLI subprocess output.
Prerequisites
At least one CLI agent must be installed on the host. gate4agent does not install them.
| CLI | Install |
|---|---|
| Claude Code | npm install -g @anthropic-ai/claude-code |
| Codex | npm install -g @openai/codex |
| Gemini | npm install -g @google/gemini-cli |
| Cursor Agent | See https://cursor.com/docs/cli |
| OpenCode | npm install -g opencode-ai (or see https://opencode.ai) |
Versioning
- 0.1.x — original 3-CLI library (Claude, Codex, Gemini)
- 0.2.0 — breaking: 6 CLIs,
TransportSession,AgentEventrenamed,PipeSessionremoved, OpenClaw fantasy transport - 0.2.1 — cleanup: OpenClaw removed (was never functional),
PipeSessionrestored for 0.1.x compatibility,TransportSessionis now a thin router overPipeSession - 0.2.2 — parser isolation: NdjsonParser trait extracted, per-CLI parser modules split out
- 0.2.3 — source tree restructure into core/pty/pipe layout; proper pipe builders+parsers for Codex, Gemini, Cursor, OpenCode (research-based, NOT yet tested against live CLI output)
See ROADMAP.md for what's next and DEBUGGING.md for known issues and mitigations.
Migration guide
0.2.0 → 0.2.1
- OpenClaw removed —
CliTool::OpenClawno longer exists. If you matched on it, delete that arm. OpenClaw was never functional (unverified daemon protocol, fictional acpx API surface). PipeSessionrestored — 0.1.x callers that usedPipeSession::spawn(config, prompt, options)compile again. ThePipeSessionnow includes SessionEnd synthesis (previously only in the 0.2.0pipe_runner).TransportSessionis now a thin wrapper overPipeSession. Its public API (spawn,subscribe,session_id,send_prompt,kill) is unchanged. Internal: no moreTransportHandleenum, no deadPtyvariant.DaemonNotRunning/DaemonProbeTimeouterror variants removed — they were only reachable via OpenClaw. Remove any match arms for these.
0.1.x → 0.2.1
-
Events:
AgentEvent::Pipe*→ neutral names. Rename all match arms:PipeText→TextPipeToolStart→ToolStartPipeToolResult→ToolResultPipeThinking→ThinkingPipeTurnComplete→TurnCompletePipeSessionStart→SessionStartPipeSessionEnd→SessionEnd
-
PipeSession::spawn— signature unchanged:PipeSession::spawn(config, prompt, options). Compiles directly. -
SpawnOptions: new unified struct. Fields:working_dir,prompt,resume_session_id,model,append_system_prompt,extra_args,env_vars. -
CliToolis now non-exhaustive in effect (2 new variants:Cursor,OpenCode). Add arms or a_ =>fallback.
Support the Project
If you find this tool useful, consider supporting development:
| Currency | Network | Address |
|---|---|---|
| USDT | TRC20 | TNxMKsvVLYViQ5X5sgCYmkzH4qjhhh5U7X |
| USDC | Arbitrum | 0xEF3B94Fe845E21371b4C4C5F2032E1f23A13Aa6e |
| ETH | Ethereum | 0xEF3B94Fe845E21371b4C4C5F2032E1f23A13Aa6e |
| BTC | Bitcoin | bc1qjgzthxja8umt5tvrp5tfcf9zeepmhn0f6mnt40 |
| SOL | Solana | DZJjmH8Cs5wEafz5Ua86wBBkurSA4xdWXa3LWnBUR94c |
License
MIT