C-Kermit over ssh
This page demonstrates how helpful it can be to run C-Kermit as a wrapper over ssh.
Please read the Introduction and Tour, and especially the ssh section of the intro, before continuing. That sets out some background that will be helpful for this conversation.
We’ll look into two common examples: nested ssh, and tar over Kermit.
Nested ssh
Let’s look at a situation many of us face frequently: sshing to one host, then from there to another, and from there maybe sudo to another account. It can be quite difficult to make scp or rsync work across all of this, and if you even can, time-consuming to set up.
Since the Kermit protocol runs in-band with your terminal session, you can exchange files from anywhere you might be.
Let’s open a nested connection.
jgoerzen@workstation:/tmp/t$ kermit -C 'ssh -A server1'
C-Kermit 10.0.416 Beta.12, 2025/03/22, for Linux+SSL (64-bit)
Copyright (C) 1985, 2025,
Trustees of Columbia University in the City of New York.
Open Source 3-clause BSD license since 2011.
Type ? or HELP for help.
Connecting via command "ssh -e none -A server1"
Escape character: Ctrl-\ (ASCII 28, FS): enabled
Type the escape character followed by C to get back,
or followed by ? to see other options.
----------------------------------------------------
jgoerzen@server1:~$ ssh -e none server2
jgoerzen@server2:~$ su -
Password:
root@server2:~#
OK, so far this is normal.
I want to note the use of -e none in the ssh command line. By default, ssh intercepts the tilde character ~ for its own purposes, which can interfere with Kermit file transfers (especially those towards the remote). -e none tells ssh to present a clean connection, which is what we need. When you run the SSH command from the Kermit command prompt (or via kermit -C), kermit uses the value set for SET SSH COMMAND to know what to run. The default for that is ssh -e none, so when you type ssh at kermit, it automatically adds the -e none.
When I manually jumped from one host to the next, I had to add that manually to make sure I maintained a clean connection. You can easily automate this in ~/.ssh/config.
Now let’s say all of a sudden we’d like to get a copy of a file only root on server2 can read. Let’s pretend that file is /bin/bash. We can send that all the way back to our local kermit on workstation with one command:
root@server2:~# kermit -Iis /bin/bash
Return to your local Kermit and give a RECEIVE command.
KERMIT READY TO SEND...
----------------------------------------------------
----------------------------------------------------
SENT: [/usr/bin/bash] To: [/tmp/t/bash] (OK)
Boom. That easy!
We can do the opposite also. Let’s say we want to receive a file on server2. In order to do this, we’ll press Ctrl-Backslash and then hit c to go to the Kermit command line back on the local machine (workstation). Then we’ll give the command to send a file. The local kermit knows the remote isn’t already running kermit, so gives the shell instructions to start it to receive the file.
root@server2:~#
[[ here I type Ctrl-\ C ]]
(Back at workstation.aaa.aaa.aaa)
----------------------------------------------------
(/tmp/t/) C-Kermit>send /bin/grep
(/tmp/t/) C-Kermit>
There we go - /bin/grep sent all the way across the link.
Since I was in Kermit command-line mode, I remain there. I can type CONNECT or C (it’s case-insensitive) to return to the shell prompt on server2. Let’s do that, and inspect the file there.
c
Connecting via command "ssh -e none -A server1"
Escape character: Ctrl-\ (ASCII 28, FS): enabled
Type the escape character followed by C to get back,
or followed by ? to see other options.
----------------------------------------------------
root@server2:~# ls -l grep
-rwxr-xr-x 1 root root 203152 Jan 4 2024 grep
The “Connecting via command” string doesn’t mean it’s establishing a new connection; it’s re-entering the session you already established, and reminding you how it was established. Anyhow, we can see the file was transferred properly.
Tar (and other piped commands) over Kermit
This is fine for one file, but you can take it further. You can actually pipe commands over Kermit. While Kermit does have a recursive send itself, let’s say you want to send a directory as a tar file.
jgoerzen@workstation:~/tmp/t$ kermit -C 'ssh server2'
C-Kermit 11.0.499, 2026/07/16, for Linux+SSL (64-bit)
Copyright (C) 1985, 2025,
Trustees of Columbia University in the City of New York.
Copyright (C) 2025-2026, John Goerzen
Open Source 3-clause BSD license since 2011.
Type ? or HELP for help.
Connecting via command "ssh -e none server2"
Escape character: Ctrl-\ (ASCII 28, FS): enabled
Type the escape character followed by C to get back,
or followed by ? to see other options.
----------------------------------------------------
jgoerzen@server2:~$ cd /usr
jgoerzen@server2:/usr$ kermit -Ii -C 'SEND /COMMAND "tar -zcf - bin 2>/dev/null" bin.tar.gz , quit'
C-Kermit 11.0.499, 2026/07/16, for Linux+SSL (64-bit)
Copyright (C) 1985, 2025,
Trustees of Columbia University in the City of New York.
Copyright (C) 2025-2026, John Goerzen
Open Source 3-clause BSD license since 2011.
Type ? or HELP for help.
Return to your local Kermit and give a RECEIVE command.
KERMIT READY TO SEND...
9 S~/ @-#Y3~^@~}0___^"U1A!
----------------------------------------------------
----------------------------------------------------
jgoerzen@server2:/usr$
Note the 2>/dev/null part of that command. tar normally writes errors and warnings to stderr. They can be things like permission denied while reading a file. SEND /COMMAND sends stdout and stderr to the remote side. If these warnings wind up interleaved with the tar file stream, they will corrupt it. So, I defensively send stderr to /dev/null as part of the command, preventing that kind of issue.
While the transfer is in progress, I see a screen like this (portions redacted):
C-Kermit 11.0.499, 2026/07/16, workstation.aaa [192.aaa.aaa.aaa]
Current Directory: /tmp/t
Network Host: ssh -e none server2
Network Type: TCP/IP
Parity: none
RTT/Timeout: 08 / 00
RECEIVING: bin.tar.gz => bin.tar.gz
File Type: BINARY
File Size:
Bytes So Far: 190281357
...10...20...30...40...50...60...70...80...90..100
Estimated Time Left: (unknown)
Transfer Rate, CPS: 3929529
Window Slots: STREAMING
Packet Type: D
Packet Count: 21834
Packet Length: 9032
Error Count: 0
Last Error:
Last Message:
X to cancel file, Z to cancel group, <CR> to resend last packet,
E to send Error packet, ^C to quit immediately, ^L to refresh screen.
Let’s exit from kermit and see what we got:
jgoerzen@workstation:/tmp/t$ ls -lh bin.tar.gz
-rw-rw-r-- 1 jgoerzen jgoerzen 245M Jul 22 15:49 bin.tar.gz
And see if it came through right:
jgoerzen@workstation:/tmp/t$ tar -ztf bin.tar.gz | tail
bin/x86_64-linux-gnu-gcc-10
bin/fakeroot-tcp
bin/smbclient
bin/fusermount3
bin/combinediff
bin/bzless
bin/virt-xml-validate
bin/systemd-umount
bin/zipsplit
bin/apt-get
Looks right!
You can use /COMMAND in both directions. Here I showed SEND /COMMAND, but you can also use RECEIVE /COMMAND. That causes the received data to be piped to a command instead of written to a file on disk.
Manual receive
So far, whenever you have initiated a transfer from the remote, the local end starts automatically receiving the file. That’s because the default for SET TERMINAL AUTODOWNLOAD is ON. If we want to receive in some other way, such as RECEIVE /COMMAND, then we need to have manual control over the receive side of things. Let’s play that out:
jgoerzen@workstation:/tmp/t$ kermit
C-Kermit 11.0.499, 2026/07/16, for Linux+SSL (64-bit)
Copyright (C) 1985, 2025,
Trustees of Columbia University in the City of New York.
Copyright (C) 2025-2026, John Goerzen
Open Source 3-clause BSD license since 2011.
Type ? or HELP for help.
(/tmp/t/) C-Kermit>set terminal autodownload off
(/tmp/t/) C-Kermit>ssh server2
Connecting via command "ssh -e none server2"
Escape character: Ctrl-\ (ASCII 28, FS): enabled
Type the escape character followed by C to get back,
or followed by ? to see other options.
----------------------------------------------------
jgoerzen@server2:~$ cd /usr
jgoerzen@server2:/usr$ kermit -Ii -C 'SEND /COMMAND "tar -zcf - bin 2>/dev/null" bin.tar.gz , quit'
C-Kermit 11.0.499, 2026/07/16, for Linux+SSL (64-bit)
Copyright (C) 1985, 2025,
Trustees of Columbia University in the City of New York.
Copyright (C) 2025-2026, John Goerzen
Open Source 3-clause BSD license since 2011.
Type ? or HELP for help.
Return to your local Kermit and give a RECEIVE command.
KERMIT READY TO SEND...
[[ here I typed Ctrl-\ C ]]
(Back at workstation.aaa.aaa.aaa)
----------------------------------------------------
(/tmp/t/) C-Kermit>receive /COMMAND "tar -ztf - | tail -n 5 > /tmp/t/tarlog.txt"
(/tmp/t/) C-Kermit>!cat tarlog.txt
bin/bzless
bin/virt-xml-validate
bin/systemd-umount
bin/zipsplit
bin/apt-get
(/tmp/t/) C-Kermit>
Here, we generated a tar file, piped it down the Kermit stream, and piped it to tar -ztf on the local machine. I took the last 5 lines of output and wrote them to tarlog.txt. Note that the stdout of the RECEIVE /COMMAND is discarded (Kermit shows you the transfer progress screen instead), so I save it off to a text file. ! is shorthand for calling the local shell to do something. I could also have typed CAT tarlog.txt.