feat(dev): tee stdout/stderr to logs/dev-YYYY-MM-DD.log - #444
Merged
Conversation
Dev logs used to live only in the tsx-watch terminal scrollback — closing the window or scrolling past the buffer lost them, so debugging an intermittent upstream 422 had no evidence trail. installFileLogger opens a per-day append fd and patches process.stdout/stderr.write to also fan out to the file. Skipped in production (log shippers handle it), under Vitest, and via CODEX_PROXY_FILE_LOG=0.
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.
Summary
process.stdout/process.stderrtologs/dev-YYYY-MM-DD.log. Patches the write functions at fd-level soconsole.log,console.warn,process.stdout.write, and the existing structuredlog.*helper all land in the file.NODE_ENV=production— log shippers handle persistence there) and under Vitest (VITEST/NODE_ENV=test); manual opt-out viaCODEX_PROXY_FILE_LOG=0.tsx watchterminal scrollback. Closing the pane or scrolling past the buffer lost them, leaving no audit trail when an upstream 422 (e.g.No tool output found for function call call_xxx) hit. We want every dev session's full stdout/stderr on disk by default.Implementation
src/utils/log-file.ts—installFileLogger({ dir, filename? })opens an append fd withopenSync, wrapsprocess.stdout.write/process.stderr.writeto callwriteSync(fd, ...)first then forward to the original, returnsuninstall()that restores the exact original function reference (not a.bindclone, so identity comparisons hold).src/utils/install-dev-logger.ts— side-effect import that gates onNODE_ENV/VITEST/CODEX_PROXY_FILE_LOGand installs into${cwd}/logs/. Errors are swallowed to stderr only — file logging must never break the process.src/index.ts— added as the very firstimportso startup logs ([Init],[Config],[ModelStore], etc.) get captured too.logs/is already covered by the root*.loggitignore.Test plan
npx vitest run tests/unit/utils/log-file.test.ts— 7 cases covering stdout/stderr tee, nested directory creation, uninstall restoration, append-mode persistence across reopens, defaultdev-YYYY-MM-DD.logfilename, boolean return value preservation.npx vitest run tests/unit/— all 1490 unit tests still pass.npx tsc --noEmit— clean.tsx watchauto-reloaded,logs/dev-2026-05-06.logmaterialized with full startup banner + subsequent request logs.Out of scope