Overview
stot is a dotfile management utility that simplifies symlinking and copying configuration files from a central dotfiles repository (~/dotfiles/) to their target locations in your home directory or system directories.
The name βstotβ likely stands for βsymlink toβ or similar, reflecting its primary purpose of creating symbolic links for dotfile management.
Features
Symlink files and directories from ~/dotfiles/ to ~/
Copy files to system directories (requires sudo)
Automatic directory creation
Safe file replacement
Visual feedback with status icons
Support for custom destination paths
Installation
Create Dotfiles Directory
Create your central dotfiles repository:
Place Script in PATH
Ensure the stot script is executable and in your PATH: chmod +x ~/workspace/source/bin/stot
Organize Dotfiles
Structure your dotfiles directory to mirror your home directory: ~/dotfiles/
βββ .vimrc
βββ .zshrc
βββ .config/
β βββ i3/
β βββ nvim/
βββ .local/
βββ bin/
stot [OPTION]... SOURCE
stot [OPTION]... SOURCE DEST
Options
Link mode (default): Creates symbolic links from ~/dotfiles/SOURCE to ~/SOURCE
Copy mode: Copies files from ~/dotfiles/SOURCE to /SOURCE using sudo
Display help message and exit
Arguments
Relative path to the file or directory within ~/dotfiles/
Optional custom destination path (relative to home directory for -l, absolute for -c)
Usage Examples
Symlinking Files
Single File
Configuration Directory
Custom Destination
# Link .vimrc from ~/dotfiles/.vimrc to ~/.vimrc
stot -l .vimrc
Copying System Files
System Configuration
Custom System Path
# Copy file to /etc/ (requires sudo)
stot -c etc/hosts etc/hosts
How It Works
Link Mode (-l)
Path Resolution
Resolves source path as ~/dotfiles/$SOURCE and destination as ~/$DEST (or ~/$SOURCE if DEST not provided)
Type Detection
Determines if source is a file or directory
Directory Handling
For directories:
Creates destination directory if it doesnβt exist
Symlinks all contents to destination
Shows: |:ok | ln | π | SOURCE
File Handling
For files:
Creates parent directory if needed
Removes existing destination file
Creates symbolic link
Shows: |:ok | ln | π | SOURCE
Copy Mode (-c)
Path Resolution
Resolves source path as ~/dotfiles/$SOURCE and destination as /$DEST (absolute path)
Validation
Verifies source file exists and destination parent directory exists
Copy Operation
Uses sudo cp to copy file to system directory
Feedback
Shows: |:ok | cp | π | DEST
Source Code
#!/usr/bin/env bash
messageOk = "|:ok |"
messageError = "|:error |"
message_ln = " ln | π |"
message_lnd = " ln | π |"
message_lna = " ln | π |"
message_cp = " cp | π |"
if (( $# == 0 )); then
echo "Please pass argumensts"
echo "Usage: stot [OPTION]... SOURCE"
exit 1 ;
fi
while getopts ":hlc" opt ; do
case $opt in
h )
echo "Usage: stot [OPTION]... SOURCE"
echo " or: stot [OPTION]... SOURCE DEST"
echo ""
echo " -l ln "
echo " -c cd "
echo " -h display this help and exit "
exit 0 ;
;;
l ) METHOD = "ln"
;;
c ) METHOD = "cp"
;;
\? )
echo "Invalid option: - $OPTARG " >&2
exit 1 ;
;;
: )
echo "Option - $OPTARG requires an argument." >&2
exit 1 ;
;;
esac
done
shift $(( $OPTIND - 1))
PASSED = $1
if [[ $1 ]]; then
# ------------------------------------------
# LN
# ------------------------------------------
if [ $METHOD == "ln" ]; then
[ $1 ] && sourcePath = $HOME /dotfiles/ $1
[ $1 ] && destPath = $HOME / $1
[ $2 ] && destPath = $HOME / $2
# IS FOLDER
# -------------
if [[ -d $sourcePath ]]; then
[ ! -d " $destPath " ] && mkdir $destPath & > /dev/null
if [ -d " $destPath " ]; then
ln -sv $sourcePath / * $destPath & > /dev/null
echo " $messageOk $message_lnd $1 "
else
echo " $messageError $destPath not found"
fi
# IS FILE
# -------------
elif [[ -f $sourcePath ]]; then
destFolderPath = $( dirname " $destPath " )
[ ! -d " $destFolderPath " ] && mkdir $destFolderPath & > /dev/null
[ -f " $destPath " ] && rm $destPath & > /dev/null
if [ -d " $destFolderPath " ]; then
ln -sv $sourcePath $destPath & > /dev/null
echo " $messageOk $message_ln $1 "
else
echo " $messageError $homeFilePath "
fi
# IS NOT VALID
# -------------
else
echo " $sourcePath is not valid"
exit 1
fi
exit 1 ;
# ------------------------------------------
# CP
# ------------------------------------------
elif [ " $METHOD " == "cp" ]; then
[ $1 ] && sourcePath = $HOME /dotfiles/ $1
[ $1 ] && destPath = / $1
[ $2 ] && destPath = / $2
# IS FILE
# -------------
if [[ -f $sourcePath ]]; then
destFolderPath = $( dirname " $destPath " )
if [ -d $destFolderPath ]; then
sudo cp $sourcePath $destFolderPath & > /dev/null
echo " $messageOk $message_cp $destPath "
else
echo " $messageError $destPath "
fi
# IS NOT VALID
# -------------
else
echo " $sourcePath is not valid"
exit 1
fi
exit 1 ;
fi
else
echo "Please pass valid source"
echo "Usage: stot [OPTION]... SOURCE"
exit 1
fi
Common Workflows
Initial Dotfiles Setup
Basic Setup
Full Desktop Setup
System Files
# Link shell configuration
stot -l .bashrc
stot -l .zshrc
# Link editor configs
stot -l .vimrc
stot -l .config/nvim
# Link git configuration
stot -l .gitconfig
# Window manager
stot -l .config/i3
stot -l .config/polybar
# Terminal
stot -l .config/alacritty
stot -l .config/kitty
# Development tools
stot -l .config/nvim
stot -l .tmux.conf
# Shell
stot -l .zshrc
stot -l .config/starship.toml
# System configuration (requires sudo)
stot -c etc/hosts
stot -c etc/pacman.conf
stot -c usr/local/bin/custom-script
New Machine Setup
Clone Dotfiles
git clone https://github.com/user/dotfiles.git ~/dotfiles
Link All Configs
# Create a setup script
cd ~/dotfiles
for config in .vimrc .zshrc .gitconfig ; do
stot -l $config
done
for dir in .config/* ; do
stot -l $dir
done
Verify Links
# Check symlinks
ls -la ~ | grep '^l'
Output Messages
Success Messages
Icon Operation Message β
Link file ` :ok ln π filename` β
Link directory ` :ok ln π dirname` β
Copy file ` :ok cp π /path/to/file`
Error Messages
Message Cause Solution Please pass argumenstsNo arguments provided Provide SOURCE argument Invalid option: -XUnknown option Use -l, -c, or -h sourcePath is not validSource doesnβt exist Check file exists in ~/dotfiles/ destPath not foundParent directory missing Check destination path
Tips & Best Practices
Version Control : Keep your ~/dotfiles/ directory under version control with git to track changes and sync across machines.
Destructive Operations : The -l mode removes existing destination files before creating symlinks. Back up important configurations first.
Directory Linking : When linking directories, stot symlinks the contents, not the directory itself, allowing for partial configuration management.
Recommended Directory Structure
~/dotfiles/
βββ .bashrc
βββ .zshrc
βββ .gitconfig
βββ .vimrc
βββ .config/
β βββ nvim/
β β βββ init.vim
β β βββ plugins.vim
β βββ i3/
β β βββ config
β βββ alacritty/
β βββ alacritty.yml
βββ .local/
β βββ bin/
β βββ custom-scripts
βββ etc/
βββ hosts
Troubleshooting
Check that:
Source file exists in ~/dotfiles/
Parent directory of destination exists
You have write permissions to destination
# Verify source exists
ls -la ~/dotfiles/your-file
# Check permissions
ls -la $( dirname ~/destination )
Permission denied when copying system files
Copy mode (-c) requires sudo privileges: # Ensure sudo is configured
sudo -v
# Run stot with -c
stot -c etc/hosts
Directory linking not working as expected
Remember that stot -l links directory contents , not the directory itself: # This links files inside .config/nvim/ to ~/.config/nvim/
stot -l .config/nvim
# Not the .config/nvim directory itself
ln Standard Unix symbolic link command
cp Standard Unix copy command
GNU Stow Alternative dotfile management tool
chezmoi Modern dotfile manager with templates
See Also