How to just get the shell output from portable_pty

use portable_pty::{CommandBuilder, NativePtySystem, PtySize, PtySystem};
use std::io::{Read, Write};
use std::sync::mpsc::{channel, Sender};
use std::thread;

fn main() {
    let pty_system = NativePtySystem::default();

    // Open the PTY
    let pair = pty_system
        .openpty(PtySize {
            rows: 24,
            cols: 80,
            pixel_width: 0,
            pixel_height: 0,
        })
        .unwrap();

    let mut cmd = CommandBuilder::new("bash");
    cmd.arg("-i");
    let mut child = pair.slave.spawn_command(cmd).unwrap();
    drop(pair.slave);

    // Create channels
    let (tx_input, rx_input) = channel::<String>(); // For sending input
    let (tx_output, rx_output) = channel::<String>(); // For receiving output

    let mut reader = pair.master.try_clone_reader().unwrap();
    let master_writer = pair.master.take_writer().unwrap();

    // Spawn a thread to read PTY output and send it to main
    thread::spawn(move || {
        handle_output_stream(reader, tx_output);
    });

   
    let tx_writer = thread::spawn(move || {
        handle_input_stream(rx_input, master_writer);
    });

    println!("You can now type commands for Bash (type 'exit' to quit):");

    let mut stored_output = String::new(); // Store output in main

    loop {
        let mut input = String::new();
        std::io::stdin().read_line(&mut input).unwrap();

        if input.trim() == "exit" {
            break;
        }

        tx_input.send(input.clone()).unwrap();

        // Collect the output received from the reader thread
        while let Ok(output) = rx_output.try_recv() {
            stored_output.push_str(&output);
            print!("{}", output);  // i get no output without this line
    }    }

    drop(tx_input);
    tx_writer.join().unwrap();

    println!("Waiting for Bash to exit...");
    let status = child.wait().unwrap();
    println!("Bash exited with status: {:?}", status);

    // Show stored output
    println!("\n===== Stored PTY Output =====\n{}", stored_output); // this line is not printed
}

fn handle_output_stream(mut reader: Box<dyn Read + Send>, tx_output: Sender<String>) {
    let mut buffer = [0u8; 1024];
    let mut collected_output = String::new();

    loop {
        match reader.read(&mut buffer) {
            Ok(0) => break, 
            Ok(n) => {
                let output = String::from_utf8_lossy(&buffer[..n]).to_string();
                collected_output.push_str(&output);
                tx_output.send(output).unwrap(); // Send to main thread
            }
            Err(e) => {
                eprintln!("Error reading from PTY: {}", e);
                break;
            }
        }
    }
}


fn handle_input_stream(rx: std::sync::mpsc::Receiver<String>, mut writer: Box<dyn Write + Send>) {
    for input in rx.iter() {
        if writer.write_all(input.as_bytes()).is_err() {
            eprintln!("Error writing to PTY");
            break;
        }
    }
}

I am trying to pass input to this pty implementation using portable_pty crate and capture only the output from the pty but instead i get a shell which is not what i want, I am a beginner in Rust and I do not understand why this happens.
I know I could do this with spawning a command using std::process::Command but that is not what i want, what i want is a persistent shell, how do i capture only the commands from the pty ?