# How to Include Custom Scripts in a Dotfiles Repository: A Complete Guide

> Learn to include custom scripts in your dotfiles repository issmirnov/dotfiles. Add executables to bin or Zsh functions to zsh/config and run install to symlink them.

- Repository: [Ivan Smirnov/dotfiles](https://github.com/issmirnov/dotfiles)
- Tags: how-to-guide
- Published: 2026-03-04

---

**You can add custom scripts to the `issmirnov/dotfiles` repository by placing executables in the `bin/` directory for command-line tools or `*.zsh` files in `zsh/config/` for Zsh functions, then running `./install` to create symlinks via Dotbot.**

Managing a personal dotfiles repository requires an extensible system for custom utilities. The `issmirnov/dotfiles` repository provides two distinct mechanisms for including your own scripts without modifying core configuration files. Whether you need standalone command-line tools or shell-specific functions, the repository's Dotbot-based architecture automatically exposes your scripts to the system after installation.

## Understanding the Two Mechanisms for Custom Scripts

The repository implements a dual-path approach to script management. Based on how you intend to use your code, you can choose between system-wide executables or Zsh-specific helpers.

### The bin/ Directory for Executable Scripts

Any file placed in the `bin/` directory becomes a system command after installation. According to the [`default.conf.yaml`](https://github.com/issmirnov/dotfiles/blob/main/default.conf.yaml) configuration, Dotbot creates a symlink from `~/bin/dotbin` to the repository's `bin/` folder. Because `~/bin` is already included in your `$PATH` (as documented in [`bin/README.md`](https://github.com/issmirnov/dotfiles/blob/main/bin/README.md)), scripts placed here are instantly accessible from any shell session.

### The Zsh Config Loader for Shell Functions

For Zsh-specific functionality, the repository loads all `*.zsh` files from `zsh/config/` and `zsh/aliases/` on startup. The `zsh/zshrc` file contains a loader loop (lines 52–57) that sources these files automatically. This mechanism is ideal for helper functions, aliases, and Zsh Line Editor (ZLE) widgets that don't need to be standalone executables.

## Step-by-Step Guide to Adding Scripts

Adding custom scripts requires no configuration file edits—just proper placement and execution permissions.

### Adding a Command-Line Tool to bin/

Place your script in the `bin/` directory (or a subdirectory) and make it executable:

```bash

# Create the script

cat > bin/hello-world.sh << 'EOF'
#!/usr/bin/env bash
echo "Hello from my custom script!"
EOF

# Make it executable

chmod +x bin/hello-world.sh

```

Run the installer to create the symlink:

```bash
./install

```

Dotbot creates the link `~/bin/dotbin` → `<repo>/bin`, making your script available as [`hello-world.sh`](https://github.com/issmirnov/dotfiles/blob/main/hello-world.sh) from any terminal.

You can also organize tools into subdirectories:

```bash

# Structure

bin/
└─ mytools/
   └─ convert-img.sh

```

After installation, invoke it directly:

```bash
convert-img.sh

```

### Adding a Zsh Helper Function

For functions that only need to exist inside Zsh sessions, create a `.zsh` file in the config directory:

```bash

# zsh/config/myutils.zsh

my_greet() {
  echo "Welcome, $USER!"
}

weather() {
  curl -s "wttr.in/${1:-$(hostname)}?0"
}

```

No installation step is required for Zsh functions—the loader in `zsh/zshrc` automatically sources these files on the next shell startup:

```zsh
find ~/.dotfiles/zsh/config ~/.dotfiles/zsh/aliases -type f -name '*.zsh' -print0 |
  while IFS= read -r -d $'\0' line; do
    source "$line"
  done

```

## How the Symlinking Works Under the Hood

The repository uses **Dotbot** to manage all file mappings. The critical configuration lives in [`default.conf.yaml`](https://github.com/issmirnov/dotfiles/blob/main/default.conf.yaml), which defines the `~/bin/dotbin: bin` mapping. This creates a symbolic link from your home directory to the repository, ensuring that any script added to the repository's `bin/` folder immediately appears in your local `~/bin/dotbin` path.

The `install` script serves as the entry point that executes Dotbot with the appropriate configuration files. When you run `./install` (or `minstall` for minimal installation), Dotbot processes [`default.conf.yaml`](https://github.com/issmirnov/dotfiles/blob/main/default.conf.yaml) and establishes all necessary symlinks while preserving existing files.

## Summary

- **Place executables in `bin/`** to create system-wide commands accessible via `$PATH` after running `./install`
- **Place `*.zsh` files in `zsh/config/` or `zsh/aliases/`** for Zsh-specific functions and aliases that load automatically
- **Run `./install`** after adding scripts to the `bin/` directory to create the necessary symlinks via Dotbot
- **Reference [`default.conf.yaml`](https://github.com/issmirnov/dotfiles/blob/main/default.conf.yaml)** to understand how Dotbot maps repository folders to your home directory
- **Check [`bin/README.md`](https://github.com/issmirnov/dotfiles/blob/main/bin/README.md)** for documentation about the `$PATH` configuration

## Frequently Asked Questions

### Do I need to modify any configuration files to add a new script?

No. The repository uses convention-based loading. Simply drop executable files into `bin/` or `.zsh` files into `zsh/config/` and they will be picked up automatically. You only need to run `./install` if you added files to `bin/`; Zsh config files are sourced dynamically on every shell startup.

### Why does the repository use a `~/bin/dotbin` symlink instead of linking directly to `~/bin`?

The [`default.conf.yaml`](https://github.com/issmirnov/dotfiles/blob/main/default.conf.yaml) maps `~/bin/dotbin` to the repository's `bin/` folder rather than replacing your entire `~/bin` directory. This approach preserves any existing binaries in your home directory while still exposing repository scripts through the `$PATH`, which typically includes `~/bin` or can be configured to include `~/bin/dotbin` specifically.

### Can I organize scripts into subdirectories within bin/?

Yes. The Dotbot configuration symlinks the entire `bin/` directory, so subdirectories like `bin/mytools/` are preserved and accessible. You can invoke scripts within subdirectories directly if your `$PATH` includes the parent directory, or reference them explicitly as `dotbin/mytools/script-name`.

### What's the difference between placing a script in bin/ versus zsh/config/?

Scripts in `bin/` become standalone executables available to all shells (Bash, Zsh, etc.) and external processes, while files in `zsh/config/` are sourced as shell code specific to Zsh. Use `bin/` for complete programs and command-line tools; use `zsh/config/` for functions, aliases, and widgets that depend on Zsh-specific features or variables.