Skip to content

Terminal input stuck after exit (raw mode not restored) #423

Open

Description

@ryuan-cw

Bug Description

After exiting happy-cli (via Ctrl+C or normal exit), the terminal input becomes stuck at whitespace. Users need to run stty sane or reset to restore normal terminal behavior.

Root Cause

The terminal raw mode is enabled in src/claude/claudeRemoteLauncher.ts:64:

process.stdin.setRawMode(true);

The cleanup code that restores terminal state is in a finally block at line 446-448:

finally {
    if (process.stdin.isTTY) {
        process.stdin.setRawMode(false);
    }
}

However, when SIGINT/SIGTERM is caught, the cleanup() function in src/claude/runClaude.ts:406 calls process.exit(0) directly:

const cleanup = async () => {
    // ... cleanup code that does NOT restore terminal state
    process.exit(0);  // Immediately terminates, skipping finally blocks
};
process.on('SIGINT', cleanup);

process.exit() terminates the process immediately, bypassing the finally block in claudeRemoteLauncher.ts. The terminal is left in raw mode.

Steps to Reproduce

  1. Run happy
  2. Wait for remote mode to start (raw mode enabled)
  3. Press Ctrl+C to exit
  4. Try typing in terminal - input appears stuck/doesn't echo

Proposed Fix

Add terminal state restoration to the cleanup function in src/claude/runClaude.ts before calling process.exit():

const cleanup = async () => {
    try {
        // ... existing cleanup code ...

        // Restore terminal state before exit
        if (process.stdin.isTTY) {
            process.stdin.setRawMode(false);
        }

        logger.debug('[START] Cleanup complete, exiting');
        process.exit(0);
    } catch (error) {
        // Also restore terminal in error path
        if (process.stdin.isTTY) {
            process.stdin.setRawMode(false);
        }
        logger.debug('[START] Error during cleanup:', error);
        process.exit(1);
    }
};

Environment

  • macOS (Darwin 25.2.0)
  • Node.js with node-pty

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    • Status
      In progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions