Currently my solution is that I wrote software that tunnels data between a virtual serial port and a real one, while displaying it to me. It uses com0com to setup the fake serial port.
Basically, m5stick is COM4, com0com is configured with fake COM6 and COM7. COM6 is connected to COM4 via my app and I can see the text in between them and inject keystroke too. VSCode talks with COM7 and all of the data from COM7 goes to COM6, to my screen, then to COM4
I also coded it so if I hit ESC, it sends the CTRL-C signal to the terminal so it brings up REPL. (pressing CTRL-C will quit the whole terminal lol)
This solution still sucks, exceptions are still printed to the LCD instead of to the COM port