How to Install Dotfiles

Last updated: March 13, 2023 | Linuxopsys

Before installing and configuring dotfiles via using git, some knowledge of it is required. Dotfiles are configuration files and cache storage for some of the applications that need to manage their own configuration.

Why are they called dotfiles? This has a simple answer, because most of the time they start their filename with a dot, for the purpose of hiding them from user. This makes sense, because no one wants to see lots of files in their home directory.

Important Subfolders of Dotfiles

Let's start by talking about some of the important folders of the correct structured dotfiles setup. Note that all of the folders that are going to be presented will be in your home folder, which will be $HOME environment variable, or '~' symbol.

  • .config: As can be seen from its name, this folder is responsible for putting configuration files of other programs. Note that programs can create their own configuration files in here, it is not totally user based. However, if some program needs to be configured, this is the place where you should start looking for.
  • .local: This folder is similar to /usr/local, which holds programs external files, or installed plugins etc. This folder can be huge, and compared to '.config', it uses lot more space than '.config'. To give an example, by default steam install games in a subfolder here.
  • .local/share: This is the main subfolder of '.local', in which programs put their data as discussed above. Neovim, steam, telegram and lots of other applications use here to hold their relevant data.
  • .cache: This folder holds temporary files or data of running programs. It is similar to '/tmp', but one important between these two are this folder does not get cleaned after each reboot. It is totally dependent on programs preference.
  • .ssh: Default folder of ssh keys, but can be moved via changing global settings of ssh.
  • .gnupg: Same purpose like ssh, this folder is to hold your gpg keys.

Customizing bash - understanding bash configuration files

Bash has some important configuration files, each one with different purposes. Explanations below can be found in $HOME directory.

  • .bashrc: This file will be run each time an interactive shell is started. This means that whenever a new terminal is run (if default shell is bash), it will run this file automatically. This is mostly used for setting aliases and configuration.
  • .profile: This file will only run if the shell is a login shell. Login shell is going to be discussed in the upcoming sections of the article. This is mostly used for setting environmental variables. There might be some examples that execute programs in the background in .profile, please know that it is a misuse.
  • .bash_history: This is the file that will store the commands produced from the user. Command limit can be changed via user preference.
  • .inputrc: This one is used to customize key bindings.
  • .bash_login: Same usage as .profile, this file can be omitted.
  • .bash_logout: This file will be run whenever the user exits the session (login shell).

Note that the files explained above are just applied to the current user, they won't apply to any other user. Some of the files also have a global option that applies for all users as well, here is the list:

  • /etc/profile
  • /etc/bashrc

These files will always be sourced before the ones that is in users home directory.

Note that these files are usually has default options that is configured by the distribution. Please edit these files carefully, as you might corrupt the system. Also as a side note, some of the other shells e.g zsh sources these files as well.

Difference Between Interactive Shell and Login Shell

interactive shell

An interactive shell is any shell instance. Note that this rule apply for any terminal application, any terminal that is spawned is an interactive shell.

When an interactive shell is opened, it would source the respected configuration file, in our case it will be .bashrc. Note that it will not source .profile.

login shell

Login shell is a special shell. This one will only run once for any user that has entered his password and successfully logged in. Login shell will source .profile. If you have made changes in '.profile', to be able to source this file you need to logout and login again.

All display managers are actually login shells. Gdm, lightdm, any display manager is a login shell. Note that tty's are login shells too, actually it is the oldest one among them.

Note that login shell sources different files as well. If you are going to enter a graphical session, other files will be sourced too. This article will cover up only for X11 display server. After the user has successfully logged in, some of the graphical-related scripts for X11 will be sourced. These files can be .xsessionrc, .xprofile or .Xsession, which sourcing these files is the responsibility of the display manager.

All 3 files have the exact purpose. This difference occurs because of the different implementations of various display managers.

There is another file for X11 called .xinitrc. Note that this file does not get sourced by any display manager, it will only and only be sourced if user is on a non-graphical session and entered the command startx.

Creating a dotfiles repository

Let's start building our dotfiles repository. To do this, we are going to create a bare git repository, otherwise git will try to configure itself to track all of the files in home directory.

git init --bare $HOME/.cfg
alias dots='/usr/bin/git --git-dir=$HOME/.cfg/ --work-tree=$HOME'
dots config --local status.showUntrackedFiles no
echo "alias dots='/usr/bin/git --git-dir=$HOME/.cfg/ --work-tree=$HOME'" >> $HOME/.bashrc


First Line: Creates a bare git repository and holds git data in a folder called '.cfg'.

Second Line: Since this bare git repository doesn't use the original '.git' folder, the command is a bit long. Let's create an alias for it so that we won't have to type that long command each time.

Third Line: Command will tell git to only track files we have added, so that it will not try to track everything in the home folder.

Fourth Line: Command will append our alias to .bashrc file.

It's done! Note that whenever a new file is going to be added to your dotfiles, remember to use the command like this:

dots add .bashrc

After that, to commit the changes:

dots commit -m "YOURMESSAGE"

And push local changes to remote repository like usual:

dots push

Configuring .bashrc

Before configuring .profile, let's customize our .bashrc first. Please open up .bashrc with your favorite editor, and put the lines below in .bashrc:

shopt -s histappend
shopt -u autocd                   
shopt -s checkwinsize  
shopt -s expand_aliases
shopt -s globstar
shopt -s dotglob
export LESS_TERMCAP_mb=$(tput bold; tput setaf 39)
export LESS_TERMCAP_md=$(tput bold; tput setaf 45)
export LESS_TERMCAP_me=$(tput sgr0)

Before adding any more commands, lets start by explaining these first. All of the lines starting with shopt is special for setting bash options.

  1. HISTSIZE: This will set the size of cached commands.
  2. HISTFILESIZE: Maximum command count that histfile will hold.
  3. histappend: Without this history will only stay on memory.
  4. autocd: Dynamically change directories without using cd command.
  5. checkwinsize: Enable updating $LINES and $COLUMNS. This one can be really important for some external commands, like man pages.
  6. expand_aliases: With this option, pressing tab when using an alias will make it expand.
  7. globstar: Enable glob option. wildcard can be used for matching any pattern. (e.g: ls /home/**/).
  8. dotglob: Include matching for hidden files.
  9. Last 3 lines are for colored manpages. You can either use tput or ascii escape sequences for it.

There are lot more configuration tools and options. Try this command to check out all of them:

shopt -s

Now, lets add some aliases to .bashrc.

alias \
	ka="killall" \
	g="git" \
	f="$FILE" \
	e="$EDITOR" \
	v="$EDITOR" \
	xcp="xclip -selection clipboard" 

alias \
	cp="cp -iv" \
	mv="mv -iv" \
	rm="rm -vI" 

These aliases are pretty simple, because of that only one of them is going to be explained.

xcp="xclip -selection clipboard" 

This one is really useful, it will copy the text to clipboard when used with a pipe.


echo 'hello world' | xcp

Now simply use Ctrl+V to paste output of piped command to anywhere.

Let's add a custom prompt. Note that the main prompt is called PS1, and it is an environment variable. Change this to set a custom prompt.

PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

Yes it looks nonsense, because of ansi escape characters. Refer to internet to look for custom prompts, just use whatever you like.

Time to add some custom functions to .bashrc.

Calculating floating numbers or using bash for arithmetical operations can be hard. Lets write a small python code with bash to make this easier.

calc() {
	echo $1 | python -c 'import sys; print(eval(sys.stdin.readline()))'

This function takes only one argument and pipes it to Python. Then Python does the magic of calculating the expression with eval, and prints the result.

calc '15+38*2.1'

Simple and easy! Use calc function to calculate any arithmetic expression.

Another example: send command output to

sendlog() {
    cat | curl -F 'f:1=<-'

This function will send the output of any command to ''. Pretty useful for sharing logs or output of commands with other people

echo 'hello' | sendlog

Open the link on your browser to see the output of piped command.

Configuring .profile

I used to believe .profile and .bashrc are the same. Please do not make the same mistake.

There is just one difference, .profile runs only once, .bashrc runs for each shell instance. To give an example:

.bashrc file:


Open up a new terminal and write:

echo $VAR

Change VAR variable:

echo $VAR 

If you close the terminal and reopen again:

echo $VAR

Will be reset. Also even without opening a terminal, if a new bash instance is run:

exec bash
echo $VAR

Enough with the examples. The question is, what should go to .profile, since it will only get run once?

The idea here is to reduce the burden of .bashrc, because putting everything in it will make the shell slower.

Just simple thinking, if .profile runs only once then lets find out what commands can be heavy, or the commands that does not need repetitive execution.

  • Environment variables: PATH, XDG variables or any other environment-related variables can be added here. Because you will not need to change these variables too often, and if some of them are long sourcing each of them on each shell can be really slow.
  • Commands that will start working in the background, like ssh-agent. Note that putting these in Xorg configuration is better, which will be covered up in next section.

X11 Configuration

X11 is the graphical display server for Linux, along with Wayland. It has several configuration files with different locations in the root filesystem. This article will only cover up for the home directory.

.xprofile: This is where to put commands that will run in the background. Graphical or not, it is not important. On some other distributions or display managers, this can be called as .xsessionrc.

.xprofile file:


dunst &
nm-applet &
conky &
eval `ssh-agent`

Note that this is just an example, since everyone can prefer different applications. The snippet above will run some graphical applications like dunst and network manager applet in the background, it will also start the ssh session.

.xinitrc file:

This file will only run if user is not in graphical screen and typed the command startx. Do not mix this with .xprofile, because the display manager is not going to run this file.

Install Dotfiles to Another System

This part is going to assume that you have made your dotfiles and pushed them to your git repository.

Make the alias again:

alias dots='/usr/bin/git --git-dir=$HOME/.cfg/ --work-tree=$HOME'

To omit file exists errors, create a temporary directory first:

mkdir tmp && cd tmp

Clone the repository:

git clone --bare <dots-url>

Move .git folder to $HOME named as .cfg:

mv .git $HOME/.cfg

Force copy everything:

cp -rf .* $HOME
cp -rf * $HOME

Now you can use your same setup anywhere.


In this tutorial, we have discussed how to make your own dotfiles and learned why are they useful. Configuring dotfiles or shell is easy if you know where to look for. In Linux, unlike Windows or MacOS most programs are configured by text rather then using a graphical application.

Getting better at configuration will not make you lose time, instead it will increase your speed and productivity.



Please add comments below to provide the author your ideas, appreciation and feedback.

Leave a Reply

Leave a Comment