364

How to set up tmux so that it starts up with specified windows opened?

Vadim Kotov
  • 7,766
  • 8
  • 46
  • 61
satoru
  • 29,529
  • 29
  • 85
  • 136

22 Answers22

346

You can write a small shell script that launches tmux with the required programs. I have the following in a shell script that I call dev-tmux. A dev environment:

#!/bin/sh
tmux new-session -d 'vim'
tmux split-window -v 'ipython'
tmux split-window -h
tmux new-window 'mutt'
tmux -2 attach-session -d

So everytime I want to launch my favorite dev environment I can just do

$ dev-tmux
sshow
  • 8,300
  • 3
  • 49
  • 80
Amjith
  • 21,516
  • 13
  • 42
  • 38
  • 5
    Thanks! I had to do some horrible escaping to get this to work combined with `bash --rcfile` to get a nice shell on scientific linux with a specific devtools version enabled. Will leave this here if someone tries to do the same. `tmux new-window -n "git lg" "scl enable devtoolset-3 'bash --rcfile – Lallen May 26 '15 at 11:43
  • 2
    I think the second line must be change, it needs -s option before 'vim'. It means " tmux new-session -d 'vim' " must be replaced by " tmux new-session -d -s 'vim' " – Ahmad Yoosofan May 06 '17 at 21:54
  • 5
    @AhmadYoosofan, The `vim` there stands for the command that is to be executed in the first (and at that time only) pane of the window. If you instead want to name the session 'vim' then yes, you're right, you got to use the `-s` flag. Whole syntax: `tmux new-session -d -s SessionName -n WindowName Command` – Mitja Jun 07 '17 at 09:46
  • 1
    watch out: if you have started a tmux session already (elsewhere), the commands could end up in the other session! @waqar-lim 's answer doesn't have this problem. – haja Jul 12 '19 at 10:42
  • So, how do I create the new session named and invoke split-window on that session? – xeruf Feb 07 '22 at 16:34
285

I was trying to create a complex grid of panes and had to deal with switching and splitting panes over and over again. Here are my learnings:

tmux new-session \;

Gets you started with a new session. To split it horizontal or vertical use split-window -h or -v subsequently, like that:

tmux new-session \; split-window -v \; split-window -h \;

Creates 3 panes, like this:

------------
|          |
|----------|
|    |     |
------------

To run commands in that panes, just add them with the send-keys 'my-command' command and C-m which executes it:

tmux new-session \; \
  send-keys 'tail -f /var/log/monitor.log' C-m \; \
  split-window -v \; \
  split-window -h \; \
  send-keys 'top' C-m \; 

And the resulting session should look like that.

------------
|  tail    |
|----------|
|    | top |
------------

Now I tried to again sub-divide the bottom left pane, so switching either back using last-pane, or in more complex windows, with the select-pane -t 1 where 1 is the number of the pane in order created starting with 0.

tmux new-session \; \
  send-keys 'tail -f /var/log/monitor.log' C-m \; \
  split-window -v \; \
  split-window -h \; \
  send-keys 'top' C-m \; \
  select-pane -t 1 \; \
  split-window -v \; \
  send-keys 'weechat' C-m \;

Does that. Basicaly knowing your way around with split-window and select-pane is all you need. It's also handy to pass with -p 75 a percentage size of the pane created by split-window to have more control over the size of the panes.

tmux new-session \; \
  send-keys 'tail -f /var/log/monitor.log' C-m \; \
  split-window -v -p 75 \; \
  split-window -h -p 30 \; \
  send-keys 'top' C-m \; \
  select-pane -t 1 \; \
  split-window -v \; \
  send-keys 'weechat' C-m \;

Which results in a session looking like that

------------------
|      tail      |
|----------------|
|          | top |
|----------|     |
| weechat  |     |
------------------

Hope that helps tmux enthusiasts in the future.

Brice
  • 37,034
  • 9
  • 83
  • 101
q9f
  • 10,548
  • 8
  • 55
  • 91
  • 2
    amazing guideline, could you guide me how to resize the width of the vertical panel after split. – MinhNV Jan 07 '19 at 04:08
  • 2
    @MinhNV `-h -p 30` creates a horizontal panel with 30% of the available height; `-v -p 75` same for vertical with 75% width. – q9f Jan 07 '19 at 11:26
  • 1
    What is the purpose of the `\:`? I've seen scripts work with and without this. – Kevin McDonough Apr 14 '19 at 16:09
  • 8
    UPDATE: `\;` passes the semicolon to tmux instead of bash, allowing the commands to be sent with one call to tmux. https://stackoverflow.com/questions/20913198/why-are-the-backslash-and-semicolon-required-with-the-find-commands-exec-optio – Kevin McDonough Apr 14 '19 at 17:17
  • 2
    `tmux new-session \; split-window -v -p 50 \; split-window -h -p 50 \; select-pane -t 0 \; split-window -h -p 50 \;` to create a pane devided into 4 panes equally spaced – ignacio Aug 04 '20 at 11:25
  • Hello, thanks for your amazing reply, what if I would like to put the mouse on and change the prefix throught the `ctrl+b : set-options -g prefix M-w` command for that session? thanks! – Omar May 10 '21 at 10:44
111

You can source different sessions from your .tmux.conf like so:

# initialize sessions
bind S source-file ~/.tmux/session1 
bind s source-file ~/.tmux/session2

And then format the sessions as you require:

#session1
new  -s SessionName -n WindowName Command
neww -n foo/bar foo
splitw -v -p 50 -t 0 bar
selectw -t 1 
selectp -t 0

This would open 2 windows, the second of which would be named foo/bar and would be split vertically in half (50%) with foo running above bar. Focus would be in window 2 (foo/bar), top pane (foo).

You can then start your preferred tmux session (in this case, session1) with PrefixShifts

Philipp Kyeck
  • 17,628
  • 15
  • 79
  • 117
jasonwryan
  • 4,246
  • 1
  • 27
  • 25
  • 6
    Can't those session be started inside .tmux.conf without requiring extra files? – Eno Mar 22 '12 at 17:11
  • 3
    One of them could: this way you can easily add more tailored sessions - and a couple of tiny text files is hardly an overhead... – jasonwryan Mar 22 '12 at 18:06
  • 1
    Wouldn't this be session nesting? I mean to run `Prefix Shift S` I need to be in tmux and sourcing your file tries to start a new session which tmux doesn't like and won't do unless you force it to. – user35915 Mar 10 '16 at 11:04
  • 1
    @user35915 it will simply not start a child session, but a separate one - on that you can switch to using e.g. prefix-s or prefix-) and prefix-( – sehe Mar 11 '16 at 22:57
  • 1
    This should be the accepted answer. However binding to s (not S) will override the built-in tmux binding for listing sessions. – count0 Jan 12 '18 at 16:50
  • and how to load a (default) session without pressing any key? just at tmux startup (as in the op's question) and without a sub-file (without having to use `source-file` command)? – bloody Nov 24 '21 at 22:13
61

Use tmuxinator - it allows you to have multiple sessions configured, and you can choose which one to launch at any given time. You can launch commands in particular windows or panes and give titles to windows. Here is an example use with developing Django applications.

Sample config file:

# ~/.tmuxinator/project_name.yml
# you can make as many tabs as you wish...

project_name: Tmuxinator
project_root: ~/code/rails_project
socket_name: foo # Not needed. Remove to use default socket
rvm: 1.9.2@rails_project
pre: sudo /etc/rc.d/mysqld start
tabs:
  - editor:
      layout: main-vertical
      panes:
        - vim
        - #empty, will just run plain bash
        - top
  - shell: git pull
  - database: rails db
  - server: rails s
  - logs: tail -f logs/development.log
  - console: rails c
  - capistrano:
  - server: ssh me@myhost

See the README at the above link for a full explanation.

Hamish Downer
  • 16,023
  • 16
  • 85
  • 81
21
:~$ tmux new-session "tmux source-file ~/session1"  

session1

neww
split-window -v 'ipython'  
split-window -h  
new-window 'mutt'  

create an alias in .bashrc

:~$ echo `alias tmux_s1='tmux new-session "tmux source-file ~/session1"'` >>~/.bashrc  
:~$ . ~/.bashrc  
:~$ tmux_s1  
m_majeres
  • 251
  • 2
  • 3
  • 1
    ~What's `neww`? I can't find that command anywhere.~ It looks like it is `new-window`, although I can't understand why you use both the long and short form. – oligofren Apr 11 '19 at 12:43
17

have a look @ https://github.com/remiprev/teamocil

you can specify your structure using YAML

windows:
  - name: sample-window
    splits:
      - cmd: vim
      - cmd:
        - ipython
        width: 50
      - cmd:
        height: 25
jassinm
  • 6,973
  • 3
  • 32
  • 42
11

If you just want to split screen on 2 panes (say horizontally), you can run this command (no tmux or shell scripts required):

tmux new-session \; split-window -h \;

You screen will look like this:

[ks@localhost ~]$                      │[ks@localhost ~]$ 
                                       │
                                       │
                                       │
                                       │
                                       │
                                       │
                                       │
                                       │
                                       │
                                       │
                                       │
[10] 0:ks@localhost:~*                  "localhost.localdomain" 19:51 31-янв-16
ks1322
  • 31,484
  • 13
  • 100
  • 154
11

First i had the approach from @jasonwryan but if you have more then 2 configs, it can get confusing.

So i created an alias function:

tmx () {
    tmux "$2" source-file "$HOME/.tmux/$1.conf";
}

In ~/.tmux/ i have multiple sessions for many uses. For example i work for different companies that have each another dev environment. So with the alias function above i can simply call: tmx company1 and load the config i need.

Update: The purpose of "$2" after the tmux command is, that you are able to pass additional tmux args.

danbruegge
  • 1,934
  • 2
  • 19
  • 26
  • 1
    Combining this with the tips from @soc1c made a super-sweet setup (https://github.com/fatso83/dotfiles/commit/35a7ed). Thanks! – oligofren Apr 04 '19 at 21:30
  • The function doesn't actually work when there isn't already an existing tmux session to hook onto (get `no server running on /tmp/tmux-1000/default`). That's why I needed to patch the command with `tmux new-session`. Ref https://github.com/fatso83/dotfiles/commit/43d481956c73826cc9cfe1d971e91e2ae3c3dfe9#diff-64848524db7ba4dea710a785457b57ecR189 – oligofren Apr 12 '19 at 07:43
  • 1
    I did my tmux setup with systemd. So there is always a session running after boot. https://wiki.archlinux.org/index.php/Tmux#Autostart_with_systemd Sorry for not mention it. – danbruegge Apr 12 '19 at 11:58
11

This script starts a session with the name "e" and three windows

#!/bin/sh 
tmux new-session -s e   -n etc -d 'cd /etc; bash -i'
tmux new-window  -t e:1 -n home   'cd ~; bash -i'
tmux new-window  -t e:2 -n log   'cd /var/log; bash -i'

tmux select-window -t e:1
tmux -2 attach-session -t e
rubo77
  • 17,707
  • 27
  • 124
  • 213
11

From my "get.all" script, which I invoke each morning to run a bunch of subsequent "get.XXX" jobs to refresh the software that I track. Some of them are auto-quitting. Others require more interaction once the get has finished (like asking to build emacs).

#!/bin/sh
tmux att -t get ||
tmux \
  new -s get -n capp \; \
  send-keys 'get.capp' C-m \; \
  neww -n emacs \; \
  send-keys 'get.emacs' C-m \; \
  neww -n git \; \
  send-keys 'get.git' C-m \; \
  neww -n mini \; \
  send-keys 'get.mini' C-m \; \
  neww -n port \; \
  send-keys 'get.port' C-m \; \
  neww -n rakudo \; \
  send-keys 'get.rakudo' C-m \; \
  neww -n neil \; \
  send-keys 'get.neil && get.neil2 && exit' C-m \; \
  neww -n red \; \
  send-keys 'get.red && exit' C-m \; \
  neww -n cpan \; \
  send-keys 'get.cpan && exit' C-m \; \
  selectw -t emacs
Randal Schwartz
  • 33,786
  • 4
  • 37
  • 62
  • 1
    somewhat unrelated, but you might want to have a look at https://github.com/r-darwish/topgrade ;) – xeruf Feb 07 '22 at 16:30
9

And this is how I do it:

#!/bin/bash

function has-session {
  tmux has-session -t name_of_my_session 2>/dev/null
}

if has-session ; then
  echo "Session already exists"
else
  cd /path/to/my/project
  tmux new-session -d -s name_of_my_session 'vim'
  tmux split-window -h -p 40 start_web_server
  tmux split-window -v
  tmux attach-session -d -t name_of_my_session
fi

I have one file for each of my project. Also you can group them to have some for work some for hobby projects.

Also you can move it to ~/bin folder, add it to PATH and give tmux_my_awesome_project name. Then you will be able to run it from each place.

Artur Małecki
  • 1,266
  • 15
  • 14
6

Try bro, it is a project bootstrapper.

It provides easy apis to interact with tmux.

It looks something like this :

#!/bin/sh
# @ project_name/tasks/init.sh
structure project_name
  window editor
    run 'vim'
  window terminal
    run 'echo happy coding ...'
focus editor
connect project_name

To launch a project all one needs to do is run following command -

bro start <project_name>

Checkout the screencast below, it shows how to get started with bro and use its tmux api.

https://user-images.githubusercontent.com/8296449/50532502-2cf3e400-0b6e-11e9-84af-c5f77a04e5cc.gif

Asur
  • 1,687
  • 4
  • 21
  • 36
5

There is a tmux plugin for this.

Check out tmux-resurrect

Restore tmux environment after system restart.

Tmux is great, except when you have to restart the computer. You lose all the running programs, working directories, pane layouts etc. There are helpful management tools out there, but they require initial configuration and continuous updates as your workflow evolves or you start new projects.

tmux-resurrect saves all the little details from your tmux environment so it can be completely restored after a system restart (or when you feel like it). No configuration is required. You should feel like you never quit tmux.

Or tmux-continuum

Features:

  • continuous saving of tmux environment
  • automatic tmux start when computer/server is turned on
  • automatic restore when tmux is started
Community
  • 1
  • 1
Syakur Rahman
  • 1,956
  • 34
  • 38
4

This works for me. Creating 5 windows with the given names and auto selecting to the home window.

new  -n home
neww -n emacs
neww -n puppet
neww -n haskell
neww -n ruby
selectw -t 1
cevaris
  • 5,489
  • 2
  • 45
  • 33
4

You can use tmux hooks to execute commands when a new session is created. Specifically, this is achieved using the session-created hook.

For example, to split the screen three ways with top running in the lower right you can add the following line to your ~/.tmux.conf file:

set-hook -g session-created 'split -h ; split -v top'

The advantage of this method is that you don't have to run tmux in any special way (i.e., shell script or alias) to get the desired result. You can also combine this with tmux new-session -A -s mysession described in this other answer such that the hook commands are only run when you first create the session and not on subsequent attachments.

This feature was added by d15d54c2c back in 2016. The first release to include it is is 2.4.

kevmitch
  • 1,108
  • 7
  • 10
4

smux.py allows you to simply list the commands you want in each pane, prefixed with a line containing three dashes.

Here's an example smux file that starts three panes.

---
echo "This is pane 1."
---
cd /tmp
git clone https://github.com/hq6/smux
cd smux
less smux.py
---
man tmux

If you put this in a file called Sample.smux, you can then run the following to launch.

pip3 install smux.py
smux.py Sample.smux

Full disclaimer: I am the author of smux.py.

merlin2011
  • 67,488
  • 40
  • 178
  • 299
2

tmuxp support JSON or YAML session configuration and a python API. A simple tmuxp configuration file to create a new session in YAML syntax is:

session_name: 2-pane-vertical
windows:
  - window_name: my test window
    panes:
      - pwd
      - pwd
gypaetus
  • 6,213
  • 2
  • 34
  • 44
2

The plugin tmux-continuum will auto save your tmux session and load it the next time tmux starts, should be easier to setup than some of the custom script solutions here.

Features:

  • continuous saving of tmux environment
  • automatic tmux start when computer/server is turned on
  • automatic restore when tmux is started

To save your session on demand you can use the tmux-resurrect plugin. tmux-resurrect is also required to run tmux-continuum

tmux-resurrect saves all the little details from your tmux environment so it can be completely restored after a system restart (or when you feel like it). No configuration is required. You should feel like you never quit tmux.

Padhraic
  • 4,396
  • 2
  • 29
  • 38
1

I've create this script. It does not need tmuxinator, ruby or others. It is just a bash script, configurable:

A file named config should contains something like this:

combo=()
combo+=('logs' 'cd /var/log; clear; pwd')
combo+=('home' 'cd ~; clear; pwd')

and the bash code should be:

#!/bin/bash

if [ -r config ]; then
    echo ""
    echo "Loading custom file"
    . config
else
    . config.dist
fi

tmux start-server

window=0
windownumber=-1

for i in "${combo[@]}"; do

    if [ $((window%2)) == 0 ]; then
        name=${i}
        ((windownumber++))
    else
        command=${i}
    fi

    if [ ${combo[0]} == "${i}" ]; then
        tmux new-session -d -s StarTmux -n "${name}"
    else
        if [ $((window%2)) == 0 ]; then
            tmux new-window -tStarTmux:$windownumber -n "${name}"
        fi
    fi

    if [ $((window%2)) == 1 ]; then
        tmux send-keys -tStarTmux:$windownumber "${command}" C-m
    fi

    ((window++))
done

tmux select-window -tStarTmux:0
tmux attach-session -d -tStarTmux
sensorario
  • 18,131
  • 26
  • 91
  • 148
  • Hi sensorario, while this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. Please take a look here: [Why and how are some answers deleted?](http://stackoverflow.com/help/deleted-answers) – bummi Apr 16 '15 at 22:13
  • N.b. amazingly, `tmux start_server` doesn't start a server on its own. See https://github.com/tmux/tmux/issues/182 – Jack Wasey Apr 08 '19 at 20:42
1

I just tried using all the ideas on this page and I didn't like any of them. I just wanted a solution that started tmux with a specific set of windows when my terminal opened. I also wanted it to be idempotent, i.e. opening a new terminal window takes over the tmux session from the previous one.

The above solutions often tend to open multiple tmux sessions and I want just one. First, I added this to my ~/.bash_profile:

tmux start-server
if [[ -z "$TMUX" ]]
then
  exec tmux attach -d -t default
fi

then I added the following to my ~/.tmux.conf:

new -s default -n emacs /usr/local/bin/emacs
neww -n shell /usr/local/bin/bash
neww -n shell /usr/local/bin/bash
selectw -t 1

now every time I start a terminal or start tmux or whatever, I either reattach to my existing desired setup (the session named default), or create a new session with that setup.

Phil Hollenback
  • 204
  • 2
  • 5
  • amazingly, `tmux start_server` doesn't start a server on its own. See https://github.com/tmux/tmux/issues/182 – Jack Wasey Apr 08 '19 at 20:41
1

You should specify it in your tmux config file (~/.tmux.conf), for example:

new mocp
neww mutt

new -d
neww
neww

(opens one session with 2 windows with mocp launched in first and mutt in second, and another detached session with 3 empty windows).

Victor Deryagin
  • 11,315
  • 1
  • 28
  • 38
1

To simply open tmux with multiple panes and run some commands, I created the following bash file:

#!/bin/bash
tmux split-window -v -p 30 -c ~/path/to/folder1
tmux split-window -h -p 66 -c ~/path/to/folder2
tmux split-window -h -p 50 'mongod'

Run the bash file to get the following:

-----------------------------------
|                                 |
|---------------------------------|
|  folder1  | folder2  |  mongod  |
-----------------------------------
Schwesi
  • 4,443
  • 8
  • 34
  • 57
  • I get error connecting to /private/tmp/tmux-501/default (No such file or directory) when runnning it on macosx – zardilior Mar 29 '22 at 20:07
  • You have to save it as a .sh file. So for example: default.sh and then run it by typing the path to that file in full. For example `/private/tmp/tmux-501/default.sh` – Schwesi Mar 30 '22 at 19:21