feat: add /codex:attach command for live log streaming#291
feat: add /codex:attach command for live log streaming#291mreza0100 wants to merge 1 commit intoopenai:mainfrom
Conversation
Adds a new `attach` subcommand to codex-companion.mjs and a matching `/codex:attach` command definition. **Problem:** Background Codex jobs (`/codex:rescue --background`) produce no live output. The only way to observe progress is to poll `/codex:status` or wait for `/codex:result` after completion — a blind black-box experience. **Solution:** `/codex:attach [job-id]` tails the job's on-disk log file in real time and exits cleanly when the job reaches a terminal status (completed, failed, cancelled). If no job ID is given, it automatically attaches to the most recent active job. Implementation details: - New `handleAttach()` async function in codex-companion.mjs - Reads the job log file path from `job.logFile` (falls back to `resolveJobLogFile` if missing) - Polls for new log content every 500ms (configurable via `--poll-interval-ms`) - Simultaneously polls job state via `listJobs()` for terminal status - Final log flush + closing line on exit - No new dependencies; uses existing state/job-control infrastructure - Does not modify any existing commands or behaviour Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c310f05758
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| job = snapshot.job; | ||
| } else { | ||
| const jobs = sortJobsNewestFirst(listJobs(workspaceRoot)); | ||
| job = jobs.find((j) => isActiveJobStatus(j.status)) ?? jobs[0] ?? null; |
There was a problem hiding this comment.
Select only active jobs when no ID is provided
When attach is run without a job ID, this fallback picks jobs[0] whenever no queued/running job exists, so a previously completed/failed job is treated as attachable instead of reporting that there is no active job. In repositories with old job history, users will unexpectedly stream stale logs and immediately exit rather than getting the intended guidance to start /codex:rescue, which contradicts the command contract in plugins/codex/commands/attach.md.
Useful? React with 👍 / 👎.
Problem
Background Codex jobs (
/codex:rescue --background) are a black box. Once fired, there's no way to observe what Codex is doing until the job completes. The only options are polling/codex:status(which shows a one-line phase summary) or waiting for/codex:result(which shows the final output only).Meanwhile, the background worker already writes every event — thread start, turn start, command executions, assistant messages, completion — to a structured log file on disk. That data just goes unobserved.
Solution
Add
/codex:attach [job-id]— a new command that tails the job's log file in real time and exits cleanly when the job reaches a terminal status.Example output:
Implementation
plugins/codex/scripts/codex-companion.mjs— newhandleAttach()function +attachcase in the dispatch switch:listJobs()+sortJobsNewestFirst()job.logFile(falls back toresolveJobLogFile())--poll-interval-ms)completed,failed,cancelled)plugins/codex/commands/attach.md— command definition following the same pattern asstatus.mdandcancel.md.What this does NOT change
state.mjs/job-control.mjsinfrastructureContext: why not MCP streaming?
We investigated whether
codex mcp-serverstreaming notifications could solve this. The Codex MCP server does emit events as MCP notifications during execution, but Claude Code silently drops them (the MCP client does not forwardnotifications/progressornotifications/messageto the model — tracked in anthropics/claude-code#4157, closed "not planned"). The log file approach is the reliable path and requires no protocol changes on either side.🤖 Generated with Claude Code