Skip to content
/ dot Public

Manage your apps, dotfiles, and their dependencies automagically

Notifications You must be signed in to change notification settings

pablopunk/dot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

80 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dot

Manage your dotfiles and their dependencies automagically

Table of Contents

Installation

$ brew install pablopunk/brew/dot

Quick Start

$ cd /path/to/dotfiles
$ tree

profiles/
├── work.lua
├── personal.lua
├── linux-server.lua
modules/
├── neovim/
│   ├── init.lua
│   └── config/
├── zsh/
│   ├── init.lua
│   └── zshrc
└── apps/
    ├── work/
    │   └── init.lua
    └── personal/
        └── init.lua

$ dot          # Link all dotfiles and install dependencies
$ dot neovim   # Only process the 'neovim' module
$ dot work     # Only process the 'work' profile

Usage

Each module under the modules/ folder needs to have at least an init.lua. If not, it will be ignored.

init.lua

Example for neovim:

-- modules/neovim/init.lua
return {
  brew = {
    { name = "neovim", options = "--HEAD" },
    "ripgrep"
  },
  config = {
    source = "./config",       -- Our config directory within the module
    output = "~/.config/nvim", -- Where the config will be linked to
  }
}

The config will be linked to the home folder with a soft link. In this case:

~/.config/nvim → ~/dotfiles/modules/neovim/config

You can also specify multiple configurations for a single module:

-- modules/multi-config/init.lua
return {
  brew = { "cursor" },
  config = {
    {
      source = "./config/settings.json",
      output = "~/Library/Application Support/Cursor/User/settings.json",
    },
    {
      source = "./config/keybindings.json",
      output = "~/Library/Application Support/Cursor/User/keybindings.json",
    }
  }
}

This will create two symlinks:

~/Library/Application Support/Cursor/User/settings.json → ~/dotfiles/modules/multi-config/config/settings.json
~/Library/Application Support/Cursor/User/keybindings.json → ~/dotfiles/modules/multi-config/config/keybindings.json

As you can see, you can declare dependencies as Homebrew packages, which makes it possible to also use dot to install GUI apps (Homebrew casks). You can create a module without any config to use it as an installer for your apps:

-- modules/apps/init.lua
return {
  brew = { "whatsapp", "spotify", "slack", "vscode" }
}

Recursive

In the example above, let's say we want to separate our apps into "work" and "personal". We could either create 2 modules on the root folder or create a nested folder for each:

-- modules/apps/work/init.lua
return {
  brew = { "slack", "vscode" }
}
-- modules/apps/personal/init.lua
return {
  brew = { "whatsapp", "spotify" }
}

Profiles

If you have several machines, you might not want to install all tools on every computer. That's why dot allows profiles.

Let's create a new "personal" profile:

-- profiles/personal.lua
return {
  modules = {
    "*",
    "!apps/work",
  }
}

In this example, running dot personal will:

  • *: Install everything under modules/, including nested directories.
  • !apps/work: Exclude the apps/work module and its submodules.

You can use the following patterns in your profile:

  • "*": Include all modules recursively.
  • "!module_name": Exclude a specific module and its submodules.
  • "module_name": Include a specific module.

For example, a work profile might look like this:

-- profiles/work.lua
return {
  modules = {
    "apps/work",
    "slack",
    "neovim",
    "zsh"
  }
}

Note

If your profile is named just like a module (e.g., profiles/neovim and modules/neovim), running dot neovim will default to the profile.

Force Mode -f

By default, dot won't touch your existing dotfiles if the destination already exists. If you still want to replace them, you can use the -f flag:

$ dot -f neovim

Note

It won't remove the existing config but will move it to a new path: <path-to-config>.before-dot.

Unlinking Configs --unlink

If you want to remove the symlinks created by dot for a specific module but keep your configuration, you can use the --unlink option:

$ dot --unlink neovim

This command will:

  • Remove the symlink at the destination specified in config.output.
  • Copy the config source from config.source to the output location.

This is useful if you want to maintain your configuration files without dot managing them anymore.

Purging Modules --purge

To completely remove a module, including uninstalling its dependencies and removing its configuration, use the --purge option:

$ dot --purge neovim

This command will:

  • Uninstall the Homebrew dependencies listed in the module's init.lua.
  • Remove the symlink or config file/directory specified in config.output.
  • Run any post_purge hooks if defined in the module.

Warning

--purge will uninstall packages from your system and remove configuration files. Use with caution.

Hooks

You can define post_install and post_purge hooks in your module's init.lua to run arbitrary commands after the module has been installed or purged.

return {
  brew = { "gh" },
  post_install = "gh auth login"
}

You can also define multi-line hooks:

return {
  brew = { "gh" },
  post_install = [[
    gh auth status | grep 'Logged in to github.com account' > /dev/null || gh auth login --web -h github.com
    gh extension list | grep gh-copilot > /dev/null || gh extension install github/gh-copilot
  ]],
}

Summary of Command-Line Options

  • Install Modules: Install dependencies and link configurations.

    $ dot             # Install all modules
    $ dot neovim      # Install only the 'neovim' module
    $ dot work        # Install only the 'work' profile
  • Force Mode: Replace existing configurations, backing them up to <config>.before-dot.

    $ dot -f          # Force install all modules
    $ dot -f neovim   # Force install the 'neovim' module
  • Unlink Configs: Remove symlinks but keep the config files in their destination.

    $ dot --unlink neovim
  • Purge Modules: Uninstall dependencies and remove configurations.

    $ dot --purge neovim

Wget Configuration

It now supports downloading files using wget. This can be useful for fetching binaries or other resources that are not available through Homebrew. You can specify a wget configuration in your module's init.lua file.

Example:

-- modules/apps/init.lua
return {
  wget = {
    {
      url = "https://app1piece.com/1Piece-4.2.1.zip",
      output = "/Applications/1Piece.app",
      zip = true,
    },
    {
      url = "https://fakedomain.com/fake.app",
      output = "/Applications/Fake.app",
    },
  },
}

This will:

  • Download the file from the specified URL.
  • Unzip it if zip = true.
  • Install it to the specified output path.

Just use it like any other module:

$ dot apps

Note

When using zip = true, make sure the output file name matches the unzipped file name. In the example above, the output is /Applications/1Piece.app because the zip file contains a file named 1Piece.app.

Examples

To do

  • dot will install dependencies and link files.
  • Support Homebrew dependencies.
  • dot -f will remove the existing configs if they exist (moves config to *.before-dot).
  • Allow post-install hooks in bash.
  • Allow installing only one module with dot neovim.
  • Allow multiple setups in one repo. Similar to "hosts" in Nix, dot work reads profiles/work.lua which includes whatever it wants from modules/.
  • Package and distribute dot through Homebrew.
  • Add --unlink option to remove symlinks and copy configs to output.
  • Add --purge option to uninstall dependencies and remove configurations.
  • Allow array of config. For example I could like two separate folders that are not siblings
  • Improve profiles syntax. For example, { "*", "apps/work" } should still be recursive except in "apps/". Or maybe accept negative patterns like { "!apps/personal" } -> everything but apps/personal.
  • Add screenshots to the README.
  • Support more ways of adding dependencies (e.g., wget binaries, git clone, apt...).
    • wget
    • git clone
    • apt
  • Unlinking dotfiles without copying. An option like dot --unlink --no-copy could be added.
  • dot --purge-all to purge all modules at once.
  • Support Mac defaults, similar to nix-darwin.
  • Support an os field. i.e os = { "mac" } will be ignored on Linux.
  • After using a profile, like dot profile1, it should remember it and all calls to dot should be done with this profile unless another profile is explicitely invoked, like dot profile2, which will replace it for the next invokations.