Skip to content

fix(api): default TERM to xterm-256color for tmux PTY attach#249

Closed
oksusucha wants to merge 1 commit into
awslabs:mainfrom
oksusucha:fix/tmux-term-env
Closed

fix(api): default TERM to xterm-256color for tmux PTY attach#249
oksusucha wants to merge 1 commit into
awslabs:mainfrom
oksusucha:fix/tmux-term-env

Conversation

@oksusucha

@oksusucha oksusucha commented May 20, 2026

Copy link
Copy Markdown

Summary

Default TERM to xterm-256color in the tmux attach subprocess environment. Uses setdefault so an explicitly configured TERM is preserved.

Problem

When CAO runs inside Docker or devcontainers where TERM is unset or set to dumb, the tmux attach-session subprocess inherits the broken value. This causes garbled terminal rendering — no colors, corrupted cursor positioning, and broken TUI output from agent CLIs (Claude Code, Kiro, Codex, etc.).

Fix

  • Copy the process environment before spawning tmux attach
  • setdefault("TERM", "xterm-256color") — only applies when TERM is missing or empty
  • Pass the patched env to subprocess.Popen

Net change: +3 lines in src/cli_agent_orchestrator/api/main.py.

Testing

  • Verified the fix applies cleanly against current main
  • Existing behavior preserved when TERM is already set (setdefault is a no-op)

Fixes #150

@haofeif haofeif requested a review from Copilot May 20, 2026 07:53
@haofeif haofeif added the bug Something isn't working label May 20, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to fix broken terminal rendering when attaching to tmux via the API WebSocket by ensuring the tmux attach subprocess has a usable TERM value (defaulting to xterm-256color) while preserving an explicitly configured TERM.

Changes:

  • Copy the parent process environment before spawning tmux attach-session.
  • Attempt to default TERM to xterm-256color.
  • Pass the patched environment to subprocess.Popen(..., env=...) for tmux attach.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/cli_agent_orchestrator/api/main.py Outdated

# Start tmux attach inside the PTY
pty_env = os.environ.copy()
pty_env.setdefault("TERM", "xterm-256color")
Comment thread src/cli_agent_orchestrator/api/main.py Outdated
Comment on lines +748 to +757
pty_env = os.environ.copy()
pty_env.setdefault("TERM", "xterm-256color")
proc = subprocess.Popen(
["tmux", "-u", "attach-session", "-t", f"{session_name}:{window_name}"],
stdin=slave_fd,
stdout=slave_fd,
stderr=slave_fd,
close_fds=True,
preexec_fn=os.setsid,
env=pty_env,
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 2 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@1d8d710). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/cli_agent_orchestrator/api/main.py 0.00% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #249   +/-   ##
=======================================
  Coverage        ?   92.84%           
=======================================
  Files           ?       65           
  Lines           ?     5507           
  Branches        ?        0           
=======================================
  Hits            ?     5113           
  Misses          ?      394           
  Partials        ?        0           
Flag Coverage Δ
unittests 92.84% <0.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

When CAO runs inside Docker or devcontainers where TERM is unset or
set to 'dumb', tmux attach inherits the broken value causing garbled
terminal rendering. Default TERM to xterm-256color before spawning
the subprocess.

Fixes awslabs#150
@oksusucha oksusucha force-pushed the fix/tmux-term-env branch from b9b50b5 to ce863d2 Compare May 20, 2026 08:42
@oksusucha oksusucha closed this May 20, 2026
haofeif pushed a commit that referenced this pull request May 23, 2026
Container and devcontainer environments routinely leave TERM unset or
set to ``dumb``. tmux's ``attach-session`` subprocess inherited that
value because the WebSocket PTY endpoint never passed ``env=`` to
``subprocess.Popen``, which broke colours, cursor positioning, and the
Ink-based TUIs that Claude Code / Codex / Gemini render. The browser-
side xterm.js then received text that was never written in a form it
could render.

Add a small ``_build_pty_env`` helper that copies the parent process
environment and forces ``TERM`` to ``xterm-256color`` when the
inherited value is unset, empty, or ``dumb``. Explicit non-dumb values
(e.g. ``screen-256color``) are preserved verbatim.

Resolves #150. Supersedes the abandoned #249, which used
``dict.setdefault`` and therefore only handled the unset case — not
``TERM=dumb`` — and shipped without unit tests (codecov flagged 0%).

Tests cover the helper (unset / empty / dumb / xterm / custom value
preserved / non-TERM env vars inherited) and a wiring guard that
patches ``subprocess.Popen`` to assert the endpoint actually hands
the corrected env to the tmux attach call.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] tmux PTY attach inherits TERM=dumb in container environments

4 participants