Add OpenCode and Codex CLI agent support#257
Open
Avyukth wants to merge 8 commits intoentireio:mainfrom
Open
Conversation
1416df8 to
6347727
Compare
Add two new AI coding agent integrations to the plugin-style agent architecture: - OpenCode: open-source AI coding CLI with .opencode/ config, no lifecycle hooks, XDG-based session storage, JSON sessions - Codex CLI: OpenAI's CLI agent with .codex/config.toml (TOML), notify hook (agent-turn-complete), JSONL session transcripts in ~/.codex/sessions/ Both agents follow existing patterns: init() self-registration, Agent interface implementation, comprehensive tests. Codex also implements HookSupport, HookHandler, TranscriptAnalyzer, and TranscriptChunker interfaces. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 0930c3197f05
… issues OpenCode hooks: - Implement HookSupport/HookHandler via TypeScript plugin at .opencode/plugins/entire.ts - Plugin subscribes to session.created and session.status (idle) events - Add hook handlers (session-created, session-idle) with full session commit flow - Register OpenCode handlers in hook registry CodeRabbit fixes: - Add parent dir creation in WriteSession for both Codex and OpenCode agents - Fix GetTranscriptPosition off-by-one for files without trailing newline - Replace filepath.Glob with filepath.WalkDir for recursive session file search - Fix force=true creating duplicate TOML notify keys in Codex hooks - Set userPrompt from hook input in Codex handler context - Remove redundant DetectPresence check in Codex agent - Extract shared extractFilePathFromLine helper to deduplicate extraction logic - Fix isEntireNotifyLine false positives matching "entire" as substring - Change FileModificationTools from mutable var to function (immutability) - Update Codex rollout types to match actual format (response_item, function_call) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: b0b842285f30
…env var
- Add explicit nil guard before calling preState.PreUntrackedFiles() in both
codex and opencode handlers (PreUntrackedFiles has a nil receiver check but
being explicit is better defensive coding)
- Resolve CODEX_PROJECT_DIR env var at write-time in buildLocalDevNotifyCommand
since Codex executes notify commands as direct argv without shell expansion
- Add test for resolved path detection in isEntireNotifyLine
- Add test verifying no unresolved ${...} templates in local dev config
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 1e577052cd36
…, scanner limit, TOML keys - (CRITICAL) Codex sends notify payload via argv not stdin; capture positional args in hook_registry.go and read -r from last arg in Codex handler - (HIGH) fileExists returns true for directories; add fileExistsAndIsRegular helper and use for transcript path checks in both handlers - (HIGH) File extraction misses actual Codex event_msg/patch_apply_begin format where file paths are HashMap keys; add extractFilePathsFromEventMsg - (LOW) Replace bufio.Scanner (64KB limit) with bufio.NewReader in ExtractModifiedFiles to handle large JSONL lines - (LOW) Fix duplicate TOML notify keys when Entire line found alongside user notify line; simplify guard to always respect user-configured notify commands Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 662e9607cc62
…, test coverage - OpenCode ResolveSessionFile now walks directory tree to find session files nested under projectID subdirectories (matching actual storage layout) - Codex buildLocalDevNotifyCommand uses paths.RepoRoot() instead of os.Getwd() to avoid baking subdirectory paths into notify command - Add tests for null/missing last-assistant-message in Codex ParseHookInput - Add tests for OpenCode recursive session file resolution with projectID nesting - Extract testThreadID constant to fix goconst lint warning Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: d60164698930
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 2638743a8f84
OpenCode: Add session-busy hook that fires on session.status busy event, capturing pre-prompt state (untracked files) at the start of each turn so session-idle can accurately detect new files created during the turn. Codex: Capture post-turn state after each agent-turn-complete as baseline for next turn's file change detection (Codex has no before-turn hook). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 97aad7243b13
Consolidate duplicated commit logic from Codex, OpenCode, and Gemini handlers into a shared commitAgentSession() function. Each agent handler is now a thin wrapper that populates an agentCommitContext struct. Also moves transitionSessionTurnEnd() and logFileChanges() to the shared file since they are used by all agents. Removes per-agent createContextFile variants in favor of a unified createContextFile() that supports both single and multi-prompt formats. Net reduction: ~160 lines of duplicated code removed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 2b7d7a03ca93
d188b0f to
b20d940
Compare
This was referenced Feb 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #245
Closes #266
Relates to #281
Summary
Adds two new AI coding agent integrations to the Entire CLI: OpenCode and Codex CLI. Both agents support full session checkpointing via hooks — capturing transcripts, file changes, prompts, and metadata on shadow branches.
As part of this work, duplicated framework code was extracted into a shared commit pipeline ("$(hooks_common_session.go)"), directly addressing issue #281's goal of separating framework from agent-specific logic. The three agent handlers (Codex, OpenCode, Gemini) that previously duplicated ~250 lines of commit logic are now thin wrappers calling a shared "$(commitAgentSession())" function.
~3,000 lines across 16 files (all new code from main's perspective).
Framework Extraction (addresses #281)
The shared "$(hooks_common_session.go)" consolidates duplicated logic from Codex, OpenCode, and Gemini handlers:
Each agent handler is now a thin wrapper that populates an "$(agentCommitContext)" struct:
This reduces the barrier for adding new agents — a new handler only needs to populate the context struct and call "$(commitAgentSession())".
Not yet extracted (future #281 work): Claude Code's "$(commitWithMetadata)" has unique subagent/summarization/incremental-checkpoint logic that requires its own pattern. The "$(Agent)" interface itself is also unchanged — broader interface refactoring is deferred to the core team per #281.
OpenCode Agent
Codex CLI Agent
Shared Infrastructure
Key Implementation Details
Codex argv payload handling:
Codex's Rust source ("$(user_notification.rs)") calls "$(command.arg(notify_payload))" with "$(stdin(Stdio::null()))". The hook registry captures positional args via "$(cobra.ArbitraryArgs)" and stores them in "$(currentHookArgs)". The handler reads from "$(args[len(args)-1])" when available, falling back to stdin.
OpenCode session-busy hook:
OpenCode fires "$(session.status)" with "$(type: "busy")" when the agent starts processing each turn. The TypeScript plugin pipes this to "$(entire hooks opencode session-busy)", which calls "$(CapturePrePromptState(sessionID, ""))" to snapshot untracked files before the agent modifies anything. The subsequent "$(session-idle)" handler uses "$(commitAgentSession())" with "$(useGitStatusForModified: true)".
Codex post-turn state capture (workaround):
Codex only exposes "$(AfterAgent)" and "$(AfterToolUse)" hooks — no "before turn" event exists. As a workaround, "$(handleCodexAgentTurnComplete)" captures state after each turn completes ("$(CapturePrePromptState)" at the end), which serves as the baseline for the next turn's "$(DetectFileChanges)".
File existence checks:
"$(fileExistsAndIsRegular())" replaces "$(fileExists())" for transcript path validation. Codex's "$(ParseHookInput)" sets "$(SessionRef)" to "$(~/.codex/sessions)" (a directory). Without the regular-file check, "$(copyFile(dir, ...))" would fail with "is a directory".
Codex JSONL file extraction:
Supports three event formats from Codex rollout transcripts:
Uses "$(bufio.NewReader)" + "$(ReadBytes('\n'))" instead of "$(bufio.Scanner)" to handle JSONL lines exceeding 64KB.
TOML hook installation (Codex):
"$(InstallHooks)" parses "$(.codex/config.toml)" line-by-line, preserving user content and comments. When a user-configured "$(notify)" line exists and "$(--force)" isn't set, installation is skipped to avoid duplicate TOML keys.
Feature Comparison: Claude Code vs OpenCode vs Codex
Hook Coverage
File Change Detection
Agent Interfaces Implemented
Remaining Gaps (Agent Limitations)
Test Plan
🤖 Generated with Claude Code