Punto is spanish for dot. Punto is a Dotfile Manager.

What dotfiles and existing managers lack is composability. Punto aims to bring composability to dotfiles.

Installing

On MacOS, you can use homebrew to install punto.

brew install rahulsom/homebrew-rahulsom/punto

On Linux, you can download directly from bintray.

Configuration

Punto can be configured using a punto.yaml file in your home directory. You can place it in a different location and pass the location using the options to the command.

Here’s a sample configuration

repositories:
- mode: git
  repo: https://github.com/mathiasbynens/dotfiles.git
  include:
  - '**/*'
  - '!**/bin/*'
  - '!**/foo/*.sh'
  into: ''
- mode: github
  repo: rahulsom/dotfiles
  branch: demo
- mode: gist
  repo: 9def705d16b8995ebdefe731d5d19e5a
  into: bin
- mode: github
  repo: rahulsom/dotfiles

ignore:
  - bin/jvm.sh
  - bin/git-changelog
  - .config/fisherman/sdkman-for-fish/.git/
  - .config/doctl

It’s a good idea to list your personal repository the last in the list of repositories. That helps the diff command suggest changes to your personal repo based on changes you have made locally.

Usage

Help

For detailed help, run

punto -h

The resulting output is

Usage: punto [-hV] [COMMAND]
Manages dotfiles.
  -h, --help      Show this help message and exit.
  -V, --version   Print version information and exit.
Commands:
  config  Prints configuration
  stage   Sets up the staging directory
  diff    Computes diff between staging and current
  update  Updates user home with latest staging contents.

Version

To see what version you’re running, run

punto -V

The resulting output is

0.1.2

Print Configuration

To see your configuration in a easier to read way, you can run

punto config

The resulting output is

userHome '/Users/rahul'
puntoHome '/Users/rahul/.punto'

git('https://github.com/mathiasbynens/dotfiles.git', into: '') {
    include '**/*', '!**/bin/*', '!**/foo/*.sh'
}
github 'rahulsom/dotfiles', branch: 'demo'
gist '9def705d16b8995ebdefe731d5d19e5a', into: 'bin'
github 'rahulsom/dotfiles'

ignore 'bin/jvm.sh', 'bin/git-changelog',
        '.config/fisherman/sdkman-for-fish/.git/', '.config/doctl'

Configuration using the same format is coming soon.

Stage Dotfiles

You typically don’t need to run this command. It is a dependency of the diff and update commands.

This will build a staging directory with dotfiles assembled based on your config. The files are staged under $puntoHome/staging.

You can stage dotfiles like this.

punto stage

The resulting output is

... Dotfiles Staged in ~/.punto/staging

The staging directory is composed as a git repository. Each repository in your configuration is layered as a commit. This shows the git log of the staging directory.

git log --graph --oneline --decorate
* 72a42a9 (HEAD -> master) Add github repo 'rahulsom/dotfiles' commit 7e811725
* c0c6c12 Add gist repo '9def705d16b8995ebdefe731d5d19e5a' commit 6e1c081c
* 7e65fe5 Add github repo 'rahulsom/dotfiles' commit a6740352
* 48c8b36 Add git repo 'https://github.com/mathiasbynens/dotfiles.git' commit 5368015b

The commit message tells you which commit in the source repository was layered. This staging directory is not intended to be used as a git repository, but git just happens to be a nice way of debugging how this directory is built.

Diff

This copies over your current dotfiles to the staging directory. That allows you to compute a diff using the unstaged changes.

punto diff

The output is

... Dotfiles Staged in ~/.punto/staging
... Diff updated in ~/.punto/staging and ~/.punto/repositories/github.com/rahulsom/dotfiles

Now you can run git diff in the staging directory to see how your dotfiles are different from your staging directory. If you want to update your personal repo based on this, you can see what’s in the checked out personal repo under ~/.punto/repositories and commit those changes.

Update

This copies over contents from a newly staged directory to your home directory.

punto update

The output is

... Dotfiles Staged in ~/.punto/staging
... Dotfiles Updated in ~

That’s it. You’re set to go. You might have to reload your shell for the changes to take effect.