PYK 2016-02-13:
Expect is typically used to automate interaction with a program, but it can also be used to mediate an interaction.  Here is a small example where both user input and program output is monitored:
#! /usr/bin/env expect
set timeout -1
proc main {argv0 argv} {
    if {[llength $argv]} {
        spawn {*}$argv
    }
    expect_background {
        Ni! {
            send_user "[lindex $argv 0] just said, \"Ni!\""
        }
    }
    expect_user {
        Ni! {
            send_user {You must not say, "Ni!"}
            exp_continue
        }
        -re . {
            send $expect_out(buffer)
            exp_continue
        }
    }
}
main $argv0 $argvAn alternate way to structure this is:
#! /bin/env expect
set timeout -1
proc main {argv0 argv} {
    if {[llength $argv]} {
        spawn {*}$argv
    }
    expect_after  {
        -i $::user_spawn_id Ni! {
            send_user {You may not say, "Ni!"}
            exp_continue
        }
        -re . {
            send $expect_out(buffer)
            exp_continue
        }
    }
    expect {
        Ni! {
            send_user "[lindex $argv 0] just said, \"Ni!\""
            exp_continue
        }
        -re . {
            exp_continue
        }
    }
}
main $argv0 $argv