Backend Abstraction Layer
All three AI backends implement the same Backend ABC. The registry maps names to singleton instances. Each backend generates CLI commands, parses JSONL output into ParsedEntry objects, and extracts token usage. Backends are pure infrastructure — they know how to talk to the AI CLI, nothing more.
Backend ABC backends/base.py get_launch_command · get_resume_command · parse_entries · extract_session_id is_task_complete · extract_tokens · extract_usage_detail · get_group_launch_command REGISTRY backends/registry.py · dict[str, Backend] {"claude": ..., "codex": ..., "gemini": ...} ClaudeBackend backends/claude/backend.py Delegates parsing to TranscriptParser --append-system-prompt for group chat --resume for session resumption CodexBackend backends/codex/backend.py AGENTS.md file for system prompt codex exec resume {id} for sessions Cumulative token tracking (delta calc) GeminiBackend backends/gemini/backend.py .gemini/system-group-*.md for prompt stdbuf -oL for line-buffered output cd {cwd} && prefix for file operations
Feature Claude Code OpenAI Codex Google Gemini
CLI Commandclaude -p --stream-json --verbosecodex exec --jsonstdbuf -oL gemini -p --stream-json
Context Window200K tokens400K tokens1M tokens
Default Modelsonnetgpt-5.3-codexgemini-2.5-flash-lite
System Prompt (Group)--append-system-promptAGENTS.md file in CWD.gemini/system-group-*.md
Session Resume--resume {session_id}codex exec resume {id}--resume {session_id}
Permissions--dangerously-skip-permissions--sandbox danger-full-access--yolo
Init Event{"type":"system","subtype":"init"}{"type":"thread.started"}{"type":"system.init"}
Completion Event{"type":"result"}{"type":"turn.completed"}{"type":"result"}
Cost TrackingcostUSD in result eventCumulative token deltastats.duration_ms, tool_calls
Transcript Parsertranscript_parser.py (shared)backends/codex/transcript.pybackends/gemini/transcript.py
Group Max Turns200 (CLAUDE_GROUP_MAX_TURNS)Backend defaultBackend default
JSONL Parsing Pipeline
Raw JSONL line from subprocess stdout backend.parse_entries() + pending state dict ParsedEntry[] role, text, content_type _entry_to_domain_event() agent_executor.py DomainEvent TextDelta, ToolInvocation... Pending state dict carries cross-line state (e.g. unmatched tool_use IDs awaiting tool_result). Passed in and returned from parse_entries().