Skip to content

[BUG] Shell tool hangs with "terminal is not fully functional" for pager-based commands #360

@cagataycali

Description

@cagataycali

Checks

  • I have updated to the latest minor and patch version of Strands
  • I have checked the documentation and this is not expected behavior
  • I have searched ./issues and there are no duplicates of my issue

Strands Version

Latest

Tools Package Version

0.2.19

Tools used

shell

Python Version

3.13

Operating System

Linux (GitHub Actions runners)

Installation Method

pip

Steps to Reproduce

  1. Use the shell tool to run any command that invokes a pager (git diff, git log, man, etc.)
  2. Observe the output shows "WARNING: terminal is not fully functional"
  3. Command hangs/times out
from strands import Agent
from strands_tools import shell

agent = Agent(tools=[shell])
result = agent.tool.shell(command="git diff main..branch --stat")  # Hangs

Expected Behavior

Commands that use pagers should either:

  1. Work correctly with proper terminal emulation
  2. Fall back to non-pager output in non-interactive mode

Actual Behavior

Output shows:

⏳ Starting Command Execution...
WARNING: terminal is not fully functional

Then the command hangs indefinitely until timeout.

Root Cause Analysis

The CommandExecutor.execute_with_pty() method in shell.py creates a PTY but does not set the TERM environment variable in the child process. When commands like git diff spawn less (the default pager), less cannot detect terminal capabilities and gets stuck.

Key code in shell.py:

def execute_with_pty(self, command: str, cwd: str, non_interactive_mode: bool):
    pid, fd = pty.fork()
    if pid == 0:  # Child process
        os.chdir(cwd)
        os.execvp("/bin/sh", ["/bin/sh", "-c", command])  # ❌ TERM not set

Evidence:

# Without fix - HANGS:
git log --oneline -3  # ❌ Times out

# With workaround - WORKS:
export GIT_PAGER=cat; git log --oneline -3  # ✅ Success

Possible Solution

Two recommended fixes:

Option 1: Set TERM in child process

if pid == 0:  # Child process
    os.environ['TERM'] = os.environ.get('TERM', 'xterm-256color')
    os.chdir(cwd)
    os.execvp("/bin/sh", ["/bin/sh", "-c", command])

Option 2: Disable pagers in non-interactive mode (safer)

if pid == 0 and non_interactive_mode:  # Child process
    os.environ['GIT_PAGER'] = 'cat'
    os.environ['PAGER'] = 'cat'
    os.environ['MANPAGER'] = 'cat'
    os.chdir(cwd)
    os.execvp("/bin/sh", ["/bin/sh", "-c", command])

Workaround

Users can work around this by:

  1. Using git --no-pager <command>
  2. Setting export GIT_PAGER=cat PAGER=cat before commands
  3. Piping through cat: git diff | cat

Related Issues

Discovered during investigation of GitHub Actions execution in automated agents.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions