Skip to content


Subversion checkout URL

You can clone with
Download ZIP


ctrl-^ escape not ideal #215

pimlott opened this Issue · 25 comments

This is issue 187 reformulated as a feature request. There are two problems with the current escape mechanism:

  • ctrl-^ is a commonly-used command in vi.
  • Sending a literal ctrl-^ is awkward.

I would suggest using the same escape mechanism as ssh (newline tilde). It has the following good properties:

  • It is already familiar to users.
  • The begin-escape sequence is two characters, thus rarely entered unintentionally.
  • The first character (newline) of the escape gets sent immediately, so the user rarely sees his input swallowed. (The necessity of sending a newline when you want the escape sequence is practically never an issue.)
  • In the rare case that you enter the begin-escape sequence unintentionally, you just hint tilde again to send a literal tilde. If the user is confused because his tilde didn't work, he is likely to do that anyway.

If you are wedded to preserving ctrl-^ . as the quit sequence, I would suggest at least making the behavior a little saner:

  • ctrl-^ ctrl-^ should send a literal ctrl-^ (not two).
  • ctrl-^ <char> should send literal ctrl-^ <char>, except for a fixed set of <char>s. They may as well follow ssh, and you may as well reserve them now even if they are not implemented.

Making the escape key configurable may be considered.


I went ahead and implemented the OpenSSH escape sequence behavior (and factored out the character to a variable so it might be able to be set by a configuration option later) in the referenced commit. I believe I implemented the OpenSSH semantics faithfully, but I'd totally be willing to believe I screwed up. (No clue if it will be wanted or merged, obviously, but I personally liked the suggestion, and figured I'd hand it over ;P.)


You rock! I haven't tried it but it looks right. Things I noticed:

  • I have no idea if '\r' starting an escape sequence is right, but if you copied from ssh I believe it.
  • You left in a literal '~'. :-)

I'll try to take a closer look later.


1) It turns out that '\r' was actually /required/: it did not work when I tested it using '\n'. I did not copy the code, however, so I'm willing to believe it should be /only/ '\r', but only checking for '\n' is apparently not right. ;P

2) Damn. :( :(


I went ahead and looked at OpenSSH's code to verify that it should be checking for both '\n' and '\r', and in fact that is the correct behavior (you will also note that it calls the variable last_was_cr, as '\r' is apparently the more canonical form).

                 * Normal character.  Record whether it was a newline,
                 * and append it to the buffer.
                last_was_cr = (ch == '\r' || ch == '\n');
                buffer_put_char(bin, ch);
@saurik saurik referenced this issue from a commit in saurik/mosh
@saurik saurik As reported by @pimlott in #215: remove literal ~. c371d08

Just an additional note on C-^, C-^ can't be typed on Spanish keyboard layouts, because it's a dead key to make âêîôû. We can type it with ^ + space, but of course that does not work with any ctrl key pressed.


Another option would be the telnet escape "^]".


FYI, in current mosh, C-^ ^ sends a literal C-^. This is documented in the manpage.

(This is analogous to screen, in which C-a a sends a literal C-a. The reason this is a good idea is so sending the escape character through a stack of n moshes or screens doesn’t take 2^n keystrokes.)

And it’s already the case that C-^ char sends a literal C-^ char, except for a fixed set of chars.


viric: in case it helps, C-~ and C-6 are equivalent to C-^.


ah right andersk, C-~ and C-6 work both. Thank you! Then, no concern from my side. But as a preference, I'd go for the openssh escape sequence too. Only because I'm used to it.


Also, I'd like to add that the message 'Press Ctrl-^ . to quit' is misleading. The ^ char is not in the same keyboard key for all keyboard layouts. I had to go to IRC and ask how to quit mosh because I was indeed pressing the key for ^ in my keyboard and it wasn't working; Take a look on how the ABNT keyboard layout (default in Brazil) places the ^ char:


@kurtkraut: We're looking for Ctrl-^, regardless of which keyboard key ^ is on. I believe the problem in your case (as determined on IRC) is that ^ is a dead key used for typing letters like ê.


Another problem with Ctrl-^ is you can't type it when using rxvt-unicode and an US-layout. rxvt-unicode uses Ctrl+Shift1 for it's weird ISO 14755 text-entry mode (which can only be disabled at compile-time), so you can't type Ctrl+Shift+6


@The-Compiler: You can leave off the Shift. ^6 isn't a character, so rxvt-unicode interprets Ctrl+6 as ^^. We should probably document this better...


@viric I'm trying those with my ES layout but can get it to work, how do yo do it exactly?


Damn, now I can see how is it. Forget it. Thanks to @andersk :-)


Perhaps what we should do is pop up the overlay bar on Ctrl-^ (or 1 second after that), explaining what Ctrl-^ . and Ctrl-^ ^ do, to help out users who type Ctrl-^ expecting it to do something to the inner application.


Just wanted to come by to tell that I've using the past two hours almost trying to figure why I couldn't get this to work on my Mountain Lion system :P

Using both iTerm2 and, and a norwegian keyboard, I ended up re-setting iTerm2, and figure out that I need to press only CTRL+6 . And not SHIFT, ^, etc.

One way I do believe helped somewhat, were the CTRL+V (Ref. feature, to display the escape sequences in raw data. When I found ^^ I had the correct one.

So my conclusion would perhaps be that this combo is a bit hard to get right for everyone without some trial and errors :)


Using Mountain Lion and iTerm using neither CTRL+6, CTRL+SHIFT+6 nor CTRL+1 works...


I don’t know why you think C-1 should work. Again, the equivalent sequences are C-^, C-~, and C-6. If none of these work (or even if only some of these work), you should probably report an iTerm bug or an iTerm2 bug.


CTRL-~ ? Great, this is assigned to hiding/showing terminal for me..
Can't mosh use some sane shortcut (or make it configurable on client side)?


I also have a dead-key ^ (it needs shift+button+space to write it). CTRL+6 was a total helper. I have indeed used a lot of time on this. Actually saying "CTRL+6" in the wait dialog would help immensely. 6 and ^ is in totally different places on my keyboard, and although a literal C ^ might've worked, it doesn't because ^ is dead here.


Hello.. I have filed feature request, which is related for ^^ issue with mosh, for mintty. Short version: instead of ^6 for ^^ mintty users need to use ^^.
Please star mintty issue if C0 key combinations are too hard to use or to remember because they aren't compatible with other terminals.


Can someone merge this change if it's working well enough?

In Mac OS, Ctrl+^ is the default key combo for going to virtual desktop 6. The way SSH quits with "Newline+." is something everyone is familiar with and should be the most familiar among almost all of Mosh's users.

mdp commented

Any progress on getting this merged in, or a plan on how to address the funkiness surround ctrl-^?

This is a pretty handy key inside of vim, which I've had to remap to avoid mosh's use of it. Would be great to move to the OpenSSH standard escape sequence.


I think, honestly, my thinking on this has changed and I would be open to moving to RET ~ . in a future major Mosh version. If somebody wants to prepare a pull request, it would be favorably received.

@keithw keithw closed this issue from a commit
@rinne rinne mosh-client: Make terminal escape character configurable
Uses environment variable MOSH_ESCAPE_KEY. Defaults to current Ctrl-^
which is somewhat problematic for many non-US keyboards.

Signed-off-by: Timo J. Rinne <>

Closes #425. Closes #215.
@keithw keithw closed this in f960a8b
@antrorsum antrorsum referenced this issue from a commit in antrorsum/mosh
@antrorsum antrorsum Squashed commit of the following:
commit c6bf3a2
Author: Barosl LEE <>
Date:   Wed May 29 12:54:29 2013 +0900

    Implement bracketed paste mode

    Allow bracketed paste mode-setting control sequences to be passed to the
    outer terminal.

    Signed-off-by: Barosl LEE <>

    Closes #430

commit 06561d3
Author: Daniel "Tracerneo" Ziółkowski <>
Date:   Fri Jun 28 04:28:32 2013 +0200

    Add support for ECMA-48 escape sequence for italic

    Closes #443

commit d871161
Author: Andrew Chin <>
Date:   Tue May 14 19:58:58 2013 -0400

    Set MACOSX_DEPLOYMENT_TARGET so that older macs can run the mosh binaries

    Closes #424

commit c3e31f1
Author: Keith Winstein <>
Date:   Wed Jun 5 19:19:05 2013 +0200

    Get rid of obsolete DM-Upload-Allowed field

commit f960a8b
Author: Timo J. Rinne <>
Date:   Thu May 16 18:09:15 2013 +0000

    mosh-client: Make terminal escape character configurable

    Uses environment variable MOSH_ESCAPE_KEY. Defaults to current Ctrl-^
    which is somewhat problematic for many non-US keyboards.

    Signed-off-by: Timo J. Rinne <>

    Closes #425. Closes #215.

commit 4792992
Author: Keith Winstein <>
Date:   Sun Apr 28 15:33:36 2013 -0400

    Rename --bind-ip to --bind-server, add =ANY option, add error checking.

    Closes #415.

commit fc70612
Author: Philipp Haselwarter <>
Date:   Tue Apr 16 18:37:40 2013 +0200

    mosh perl wrapper: New option --bind-ip={ssh|IP}

    Allow overriding the switch passed to mosh-server from -s to -i IP.

    Signed-off-by: Philipp Haselwarter <>

commit 9314ea1
Author: Jérémie Courrèges-Anglas <>
Date:   Tue Apr 16 11:11:45 2013 +0200

    use betoh64 if be64toh not found

    Instead of looking for htobe64 which is be available both when
    be64toh or betoh64 are, check for the latter functions.  If we
    find betoh64 but not be64toh, use compat #defines.  If both
    can't be found, search for OSX' OSSwapHostToBigInt64.
    Also include sys/types.h in byteorder.h (which is necessary for
    byteorder functions on OpenBSD), and incidentally fixes build

    Fixes build on OpenBSD

    Signed-off-by: Jérémie Courrèges-Anglas <>

commit 24b078a
Author: Jérémie Courrèges-Anglas <>
Date:   Tue Apr 16 11:09:42 2013 +0200

    workaround for systems not providing pselect

    using a mix of good old select and sigprocmask

    Signed-off-by: Jérémie Courrèges-Anglas <>

commit fbd2d18
Author: Andrew Chin <>
Date:   Sat Mar 30 23:26:52 2013 -0400

    In the OSX build script, link with system libs.

    Previously, mosh was linking with macports-provided libs in
    /opt/local/lib, which was not portable to users without macports

    Closes #411

commit 8ff636d
Author: Anders Kaseorg <>
Date:   Tue Apr 9 18:04:43 2013 -0400

    Work around automake bug that dropped portability warnings

    There’s a bug in automake ≥ 1.10, < 1.12 where ‘-Wall foreign’
    incorrectly turns off warnings about portability issues.  To get
    consistent results across automake versions, use ‘foreign -Wall’

    Signed-off-by: Anders Kaseorg <>

    Closes #413

commit fb39fe2
Author: Anton Lundin <>
Date:   Tue Jan 22 20:29:01 2013 +0100

    Simplify pipe management

    We don't need to write perl like C.

commit 1b9915f
Author: Keith Winstein <>
Date:   Wed Mar 27 18:34:21 2013 -0400

    Bump version to 1.2.4a

commit 9669178
Author: Keith Winstein <>
Date:   Wed Mar 27 15:21:20 2013 -0400

    Eliminate test program (closes #408)

    This test doesn't return an error on failure and also was triggering a
    stack protector warning on some platforms. We have an end-to-end test of
    OCB in src/tests/ that seems to work well.

commit 4a37359
Author: Alexander Chernyakhovsky <>
Date:   Wed Mar 27 14:49:58 2013 -0400

    Update mosh.spec for mosh 1.2.4

commit 172b1e5
Author: Alexander Chernyakhovsky <>
Date:   Wed Mar 27 02:15:25 2013 -0400

    Cast time_elapsed to int before calling human_readable_duration

    When attempting to build againt EPEL 5, it was noticed that
    human_readable_duration expects an int, but time_elapsed is an
    integer.  Explicitly static_cast<int>( time_elapsed ) to appease older

commit 688bf21
Author: Keith Winstein <>
Date:   Wed Mar 27 00:28:47 2013 -0400

    Bump version to 1.2.4

commit 61c6ee6
Author: Keith Winstein <>
Date:   Wed Mar 27 00:26:59 2013 -0400

    Send SIGSTOP to whole process group on suspend (closes #401)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.