code: func (ns *NodeSession) pipeInOut(shell io.ReadWriteCloser) {
  	// copy from the remote shell to the local output
  	go func() {
  		defer ns.closer.Close()
  		_, err := io.Copy(ns.stdout, shell)
  		if err != nil {
  			log.Errorf(err.Error())
  		}
  	}()
  	// copy from the local input to the remote shell:
  	go func() {
  		defer ns.closer.Close()
  		buf := make([]byte, 128)
  		for {
  			n, err := ns.stdin.Read(buf)
  			if err != nil {
  				fmt.Fprintln(ns.stderr, trace.Wrap(err))
  				return
  			}
  			if n > 0 {
  				_, err = shell.Write(buf[:n])
  				if err != nil {
  					ns.ExitMsg = err.Error()
  					return
  				}
  			}
  		}
  	}()
  }
docs: // pipeInOut launches two goroutines: one to pipe the local input into the remote shell,
  // and another to pipe the output of the remote shell into the local output