145

I'm writing a shell script that creates / attaches or switches to a given session, depending on whether one is inside tmux and the session exists.

I've got everything working great except for the case requiring the creation of a new tmux session from within a tmux session.

When my script executes tmux new-session -s name, I get the following output:

sessions should be nested with care, unset $TMUX to force

I don't actually want to nest sessions, my goal is to create another separate session and switch to it from within a tmux session.

Is this possible?

reinierpost
  • 8,425
  • 1
  • 38
  • 70
Michael Robinson
  • 29,278
  • 12
  • 104
  • 130

9 Answers9

213

The quickest way (assuming you use ctrl-b as your command prefix) is:

ctrl-b :new

To create a new session, then

ctrl-b s

to interactively select and attach to the session.

msharp
  • 3,000
  • 2
  • 19
  • 6
46

How to create the script

This script will check if a session exists. If session does not exist create new session and attach to it. If session does exist nothing happens and we attach to that session. Feel free to replace `~/development' with project name.

$ touch ~/development && chmod +x ~/development

# ~/development

tmux has-session -t development
if [ $? != 0 ]
then
  tmux new-session -s development
fi
tmux attach -t development  

New session from terminal

Let's create two detached sessions, list them, attach to one and then from within tmux cycle through sessions.

tmux new -s name -d works from inside tmux because we're creating a new detached session. Otherwise you'll get a nesting error.

$ tmux new -s development -d
$ tmux new -s foo -d
$ tmux ls
> development: 1 windows (created Wed Jan 13 11:31:38 2016) [204x54]
> foo: 1 windows (created Wed Jan 13 11:31:38 2016) [204x54]
$ tmux attach -t
$ tmux ls
> development: 1 windows (created Wed Jan 13 11:31:38 2016) [204x54] (attached)
> foo: 1 windows (created Wed Jan 13 11:31:38 2016) [204x54]

New session from within tmux

We are now inside or better known as attached to our target session. If we try to create a new session while attached it will result in a nesting error.

$ tmux new -s bar
> sessions should be nested with care, unset $TMUX to force

To solve this we create a new detached session. e.g.,

$ tmux new -s bar -d
$ tmux ls
> development: 1 windows (created Wed Jan 13 11:31:38 2016) [204x54] (attached)
> foo: 1 windows (created Wed Jan 13 11:31:38 2016) [204x54]
> bar: 1 windows (created Wed Jan 13 17:19:35 2016) [204x54]

Cycle (switch) Sessions

  • Prefix ( previous session
  • Prefix ) next session

note: Prefix is Ctrl-bby default. You can bind Prefix to Ctrl-a and in Mac OSX you can change Caps Lock to ctrl system preferences > keyboard > modifier keys

Attach to a session using command mode while inside tmux

Trying to attach to a session without detaching will result in an error.

$ tmux attach -t development
> sessions should be nested with care, unset $TMUX to force

Instead use command mode Prefix : then type attach -t session_name and hit enter.

Yonk
  • 471
  • 5
  • 7
  • 1
    Thanks for the very complete answer, this answered a few of my questions all at once! – mdekkers Jun 01 '18 at 04:33
  • What might output `no current client` with such a setup on the default config on the very first attach to a new main Tmux session? For example, `TMUX='' tmux new-session -ds 'main'; exec tmux attach -t 'main';` outside of Tmux and without `main` prior set. – Artfaith Mar 20 '23 at 20:34
29

Using this works for me:

TMUX= tmux new-session -d -s name
tmux switch-client -t name

The TMUX= on the first line is required so tmux doesn't throw a sessions should be nested with care, unset $TMUX to force message.

  • 1
    Works great in my script after changing first line to: `TMUX=\`tmux new-session -d -s name\`` – Michael Robinson May 07 '13 at 02:04
  • 1
    @MichaelRobinson, that just coincidentally working for you. Backticks are used to capture output from a command, but `tmux new-session -d -s name` does not generate any output to capture. Rather it's the fact than `name` is shared between the two commands. – zrajm Jan 25 '23 at 01:55
  • 1
    shorthand: `tmux switchc -t "$(tmux new -dP)"` – robrecord Feb 01 '23 at 13:15
20

All the commands you can launch within your terminal, like tmux new -s sessionName can be launched from within tmux by pressing the trigger key (eg: ctrl-b) then : then the command without the starting tmux part.

As a result, ctrl-b : followed by new -s sessionName will do exactly what you want and give a name to your session. It also switches automatically to the new session.

Morlock
  • 6,880
  • 16
  • 43
  • 50
14

You can try unset TMUX first, this works for me.

Xiao Hanyu
  • 1,402
  • 16
  • 11
8

at user2354696's advice I use following key bindings to create a new session or "clone" an existing session

bind-key N run-shell 'TMUX= tmux new-session -d \; switch-client -n'
bind-key C run-shell 'TMUX= tmux new-session -t $(tmux display-message -p #S) -s $(tmux display-message -p #S-clone) -d \; switch-client -n \; display-message "session #S cloned"'
3

TL;DR

tmux switchc -t `tmux new -dP`

How it works

To create a new session and switch to it, from insde a tmux session and without using tmux commands, you need to do it in two steps.

  1. Create the session with new-session in a detatched way with -d, print out the name with -P. Capture this output.
NEW_SESSION=`tmux new-session -dP`
  1. Use the output to switch the client (your terminal window) to different session with switch-client. Pass your new session as the target with -t.
tmux switch-client -t $NEW_SESSION

One-liner

You can create a one-liner that does this:

tmux switch-client -t `tmux new-session -dP`

or in shorthand:

tmux switchc -t `tmux new -dP`
robrecord
  • 504
  • 5
  • 15
  • 2
    This a good variation to the accepted answer – ranemirusG Feb 22 '23 at 03:01
  • 1
    Awesome answer and mostly what I was looking for. I found that if binding to a key the `tmux` is not needed and just `new-session` will also bring you to the newly created session. In other words `bind-key -N "New Client Session" C-a new-session` will create the new session and then switch to that as well (as far as I see I don't have any other settings to automagically switch to the new session when created) – Keith E. Truesdell Feb 27 '23 at 19:58
0

As mentioned by the comment here, use

Ctrl-b :new -s <name>
General Grievance
  • 4,555
  • 31
  • 31
  • 45
0

I created a zsh/zle function tmx:

  • When invoked from the command line as just tmx or using a bound key (my case below F4) it invokes fzf to quickly switch to available tmux sessions with auto-completion and session preview on the right.

    (The function was inspired by https://waylonwalker.com/tmux-fzf-session-jump/, see also Quick jump to tmux session.)

  • When invoked as tmux my-session it attaches to or creates a new session my-session.

  • It works both within and outside an existing session. If invoked within a session it switches the client.

function tmx {
    [ -n "$ZLE_STATE" ] && trap 'zle reset-prompt' EXIT
    local tmux item
    tmux="$(which tmux)" || return $?
    if [ -z "$1" ] ; then
        item="$($tmux list-sessions -F '#{session_name}' |\
            fzf --header jump-to-session --preview "$tmux capture-pane -pt {}")" || return 2
    else
        item="$1"
    fi
    (
        # Restore the standard std* file descriptors for tmux.
        # https://unix.stackexchange.com/a/512979/22339
        exec </dev/tty; exec <&1;
        if [ -z "$TMUX" ] ; then
            # Running insided tmux.
            $tmux new-session -As "$item"
        else
            # Attempt to create a new session in case there none with that name.
            $tmux new-session -ds "$item" 2>/dev/null || true
            $tmux switch-client -t "$item"
        fi
    )
}
zle -N tmx
bindkey '\eOS' tmx  # Bind the function to F4.
Petr
  • 62,528
  • 13
  • 153
  • 317