test: fix `pyenv` configuration in vagrant
[dotbot.git] / README.md
blobcf99c3b504c647dea3c50610dda5cddc791c8eec
1 # Dotbot [![Build Status](https://github.com/anishathalye/dotbot/workflows/CI/badge.svg)](https://github.com/anishathalye/dotbot/actions?query=workflow%3ACI)
3 Dotbot makes installing your dotfiles as easy as `git clone $url && cd dotfiles
4 && ./install`, even on a freshly installed system!
6 - [Rationale](#rationale)
7 - [Getting Started](#getting-started)
8 - [Configuration](#configuration)
9 - [Directives](#directives) ([Link](#link), [Create](#create), [Shell](#shell), [Clean](#clean), [Defaults](#defaults))
10 - [Plugins](#plugins)
11 - [Command-line Arguments](#command-line-arguments)
12 - [Wiki][wiki]
14 ---
16 ## Rationale
18 Dotbot is a tool that bootstraps your dotfiles (it's a [Dot]files
19 [bo]o[t]strapper, get it?). It does *less* than you think, because version
20 control systems do more than you think.
22 Dotbot is designed to be lightweight and self-contained, with no external
23 dependencies and no installation required. Dotbot can also be a drop-in
24 replacement for any other tool you were using to manage your dotfiles, and
25 Dotbot is VCS-agnostic -- it doesn't make any attempt to manage your dotfiles.
27 See [this blog
28 post](https://www.anishathalye.com/2014/08/03/managing-your-dotfiles/) or more
29 resources on the [tutorials
30 page](https://github.com/anishathalye/dotbot/wiki/Tutorials) for more detailed
31 explanations of how to organize your dotfiles.
33 ## Getting Started
35 ### Starting Fresh?
37 Great! You can automate the creation of your dotfiles by using the
38 user-contributed [init-dotfiles][init-dotfiles] script. If you'd rather use a
39 template repository, check out [dotfiles_template][dotfiles-template]. Or, if
40 you're just looking for [some inspiration][inspiration], we've got you covered.
42 ### Integrate with Existing Dotfiles
44 The following will help you get set up using Dotbot in just a few steps.
46 If you're using **Git**, you can add Dotbot as a submodule:
48 ```bash
49 cd ~/.dotfiles # replace with the path to your dotfiles
50 git init # initialize repository if needed
51 git submodule add https://github.com/anishathalye/dotbot
52 git config -f .gitmodules submodule.dotbot.ignore dirty # ignore dirty commits in the submodule
53 cp dotbot/tools/git-submodule/install .
54 touch install.conf.yaml
55 ```
57 If you're using **Mercurial**, you can add Dotbot as a subrepo:
59 ```bash
60 cd ~/.dotfiles # replace with the path to your dotfiles
61 hg init # initialize repository if needed
62 echo "dotbot = [git]https://github.com/anishathalye/dotbot" > .hgsub
63 hg add .hgsub
64 git clone https://github.com/anishathalye/dotbot
65 cp dotbot/tools/hg-subrepo/install .
66 touch install.conf.yaml
67 ```
69 If you are using PowerShell instead of a POSIX shell, you can use the provided
70 `install.ps1` script instead of `install`.
72 To get started, you just need to fill in the `install.conf.yaml` and Dotbot
73 will take care of the rest. To help you get started we have [an
74 example](#full-example) config file as well as [configuration
75 documentation](#configuration) for the accepted parameters.
77 Note: The `install` script is merely a shim that checks out the appropriate
78 version of Dotbot and calls the full Dotbot installer. By default, the script
79 assumes that the configuration is located in `install.conf.yaml` the Dotbot
80 submodule is located in `dotbot`. You can change either of these parameters by
81 editing the variables in the `install` script appropriately.
83 Setting up Dotbot as a submodule or subrepo locks it on the current version.
84 You can upgrade Dotbot at any point. If using a submodule, run `git submodule
85 update --remote dotbot`, substituting `dotbot` with the path to the Dotbot
86 submodule; be sure to commit your changes before running `./install`, otherwise
87 the old version of Dotbot will be checked out by the install script. If using a
88 subrepo, run `git fetch && git checkout origin/master` in the Dotbot directory.
90 If you prefer, you can install Dotbot from [PyPI] and call it as a command-line
91 program:
93 ```bash
94 pip install dotbot
95 touch install.conf.yaml
96 ```
98 In this case, rather than running `./install`, you can invoke Dotbot with
99 `dotbot -c <path to configuration file>`.
101 ### Full Example
103 Here's an example of a complete configuration.
105 The conventional name for the configuration file is `install.conf.yaml`.
107 ```yaml
108 - defaults:
109     link:
110       relink: true
112 - clean: ['~']
114 - link:
115     ~/.tmux.conf: tmux.conf
116     ~/.vim: vim
117     ~/.vimrc: vimrc
119 - create:
120     - ~/downloads
121     - ~/.vim/undo-history
123 - shell:
124   - [git submodule update --init --recursive, Installing submodules]
127 The configuration file is typically written in YAML, but it can also be written
128 in JSON (which is a [subset of YAML][json2yaml]). JSON configuration files are
129 conventionally named `install.conf.json`.
131 ## Configuration
133 Dotbot uses YAML or JSON-formatted configuration files to let you specify how
134 to set up your dotfiles. Currently, Dotbot knows how to [link](#link) files and
135 folders, [create](#create) folders, execute [shell](#shell) commands, and
136 [clean](#clean) directories of broken symbolic links. Dotbot also supports user
137 [plugins](#plugins) for custom commands.
139 **Ideally, bootstrap configurations should be idempotent. That is, the
140 installer should be able to be run multiple times without causing any
141 problems.** This makes a lot of things easier to do (in particular, syncing
142 updates between machines becomes really easy).
144 Dotbot configuration files are arrays of tasks, where each task
145 is a dictionary that contains a command name mapping to data for that command.
146 Tasks are run in the order in which they are specified. Commands within a task
147 do not have a defined ordering.
149 When writing nested constructs, keep in mind that YAML is whitespace-sensitive.
150 Following the formatting used in the examples is a good idea. If a YAML
151 configuration file is not behaving as you expect, try inspecting the
152 [equivalent JSON][json2yaml] and check that it is correct.
154 ## Directives
156 Most Dotbot commands support both a simplified and extended syntax, and they
157 can also be configured via setting [defaults](#defaults).
159 ### Link
161 Link commands specify how files and directories should be symbolically linked.
162 If desired, items can be specified to be forcibly linked, overwriting existing
163 files if necessary. Environment variables in paths are automatically expanded.
165 #### Format
167 Link commands are specified as a dictionary mapping targets to source
168 locations. Source locations are specified relative to the base directory (that
169 is specified when running the installer). If linking directories, *do not*
170 include a trailing slash.
172 Link commands support an optional extended configuration. In this type of
173 configuration, instead of specifying source locations directly, targets are
174 mapped to extended configuration dictionaries.
176 | Parameter | Explanation |
177 | --- | --- |
178 | `path` | The source for the symlink, the same as in the shortcut syntax (default: null, automatic (see below)) |
179 | `create` | When true, create parent directories to the link as needed. (default: false) |
180 | `relink` | Removes the old target if it's a symlink (default: false) |
181 | `force` | Force removes the old target, file or folder, and forces a new link (default: false) |
182 | `relative` | Use a relative path to the source when creating the symlink (default: false, absolute links) |
183 | `canonicalize` | Resolve any symbolic links encountered in the source to symlink to the canonical path (default: true, real paths) |
184 | `glob` | Treat a `*` character as a wildcard, and perform link operations on all of those matches (default: false) |
185 | `if` | Execute this in your `$SHELL` and only link if it is successful. |
186 | `ignore-missing` | Do not fail if the source is missing and create the link anyway (default: false) |
187 | `exclude` | Array of paths to remove from glob matches. Uses same syntax as `path`. Ignored if `glob` is `false`. (default: empty, keep all matches) |
189 Dotbot uses [glob.glob](https://docs.python.org/3/library/glob.html#glob.glob)
190 to resolve glob paths. However, due to its design, using a glob path such as
191 `config/*` for example, will not match items that begin with `.`. To
192 specifically capture items that begin with `.`, you will need to use a path
193 like this: `config/.*`.
195 #### Example
197 ```yaml
198 - link:
199     ~/.config/terminator:
200       create: true
201       path: config/terminator
202     ~/.vim: vim
203     ~/.vimrc:
204       relink: true
205       path: vimrc
206     ~/.zshrc:
207       force: true
208       path: zshrc
209     ~/.hammerspoon:
210       if: '[ `uname` = Darwin ]'
211       path: hammerspoon
214 If the source location is omitted or set to `null`, Dotbot will use the
215 basename of the destination, with a leading `.` stripped if present. This makes
216 the following two config files equivalent.
218 Explicit sources:
220 ```yaml
221 - link:
222     ~/bin/ack: ack
223     ~/.vim: vim
224     ~/.vimrc:
225       relink: true
226       path: vimrc
227     ~/.zshrc:
228       force: true
229       path: zshrc
230     ~/.config/:
231       glob: true
232       path: config/*
233       relink: true
234       exclude: [ config/Code ]
235     ~/.config/Code/User/:
236       create: true
237       glob: true
238       path: config/Code/User/*
239       relink: true
242 Implicit sources:
244 ```yaml
245 - link:
246     ~/bin/ack:
247     ~/.vim:
248     ~/.vimrc:
249       relink: true
250     ~/.zshrc:
251       force: true
252     ~/.config/:
253       glob: true
254       path: config/*
255       relink: true
256       exclude: [ config/Code ]
257     ~/.config/Code/User/:
258       create: true
259       glob: true
260       path: config/Code/User/*
261       relink: true
264 ### Create
266 Create commands specify empty directories to be created.  This can be useful
267 for scaffolding out folders or parent folder structure required for various
268 apps, plugins, shell commands, etc.
270 #### Format
272 Create commands are specified as an array of directories to be created. If you
273 want to use the optional extended configuration, create commands are specified
274 as dictionaries. For convenience, it's permissible to leave the options blank
275 (null) in the dictionary syntax.
277 | Parameter | Explanation |
278 | --- | --- |
279 | `mode` | The file mode to use for creating the leaf directory (default: 0777) |
281 The `mode` parameter is treated in the same way as in Python's
282 [os.mkdir](https://docs.python.org/3/library/os.html#mkdir-modebits). Its
283 behavior is platform-dependent. On Unix systems, the current umask value is
284 first masked out.
286 #### Example
288 ```yaml
289 - create:
290     - ~/downloads
291     - ~/.vim/undo-history
292 - create:
293     ~/.ssh:
294       mode: 0700
295     ~/projects:
298 ### Shell
300 Shell commands specify shell commands to be run. Shell commands are run in the
301 base directory (that is specified when running the installer).
303 #### Format
305 Shell commands can be specified in several different ways. The simplest way is
306 just to specify a command as a string containing the command to be run.
308 Another way is to specify a two element array where the first element is the
309 shell command and the second is an optional human-readable description.
311 Shell commands support an extended syntax as well, which provides more
312 fine-grained control.
314 | Parameter | Explanation |
315 | --- | --- |
316 | `command` | The command to be run |
317 | `description` | A human-readable message describing the command (default: null) |
318 | `quiet` | Show only the description but not the command in log output (default: false) |
319 | `stdin` | Allow a command to read from standard input (default: false) |
320 | `stdout` | Show a command's output from stdout (default: false) |
321 | `stderr` | Show a command's error output from stderr (default: false) |
323 Note that `quiet` controls whether the command (a string) is printed in log
324 output, it does not control whether the output from running the command is
325 printed (that is controlled by `stdout` / `stderr`). When a command's `stdin` /
326 `stdout` / `stderr` is not enabled (which is the default), it's connected to
327 `/dev/null`, disabling input and hiding output.
329 #### Example
331 ```yaml
332 - shell:
333   - chsh -s $(which zsh)
334   - [chsh -s $(which zsh), Making zsh the default shell]
335   -
336     command: read var && echo Your variable is $var
337     stdin: true
338     stdout: true
339     description: Reading and printing variable
340     quiet: true
341   -
342     command: read fail
343     stderr: true
346 ### Clean
348 Clean commands specify directories that should be checked for dead symbolic
349 links. These dead links are removed automatically. Only dead links that point
350 to somewhere within the dotfiles directory are removed unless the `force`
351 option is set to `true`.
353 #### Format
355 Clean commands are specified as an array of directories to be cleaned.
357 Clean commands also support an extended configuration syntax.
359 | Parameter | Explanation |
360 | --- | --- |
361 | `force` | Remove dead links even if they don't point to a file inside the dotfiles directory (default: false) |
362 | `recursive` | Traverse the directory recursively looking for dead links (default: false) |
364 Note: using the `recursive` option for `~` is not recommended because it will
365 be slow.
367 #### Example
369 ```yaml
370 - clean: ['~']
372 - clean:
373     ~/:
374       force: true
375     ~/.config:
376       recursive: true
379 ### Defaults
381 Default options for plugins can be specified so that options don't have to be
382 repeated many times. This can be very useful to use with the link command, for
383 example.
385 Defaults apply to all commands that come after setting the defaults. Defaults
386 can be set multiple times; each change replaces the defaults with a new set of
387 options.
389 #### Format
391 Defaults are specified as a dictionary mapping action names to settings, which
392 are dictionaries from option names to values.
394 #### Example
396 ```yaml
397 - defaults:
398     link:
399       create: true
400       relink: true
403 ### Plugins
405 Dotbot also supports custom directives implemented by plugins. Plugins are
406 implemented as subclasses of `dotbot.Plugin`, so they must implement
407 `can_handle()` and `handle()`. The `can_handle()` method should return `True`
408 if the plugin can handle an action with the given name. The `handle()` method
409 should do something and return whether or not it completed successfully.
411 All built-in Dotbot directives are written as plugins that are loaded by
412 default, so those can be used as a reference when writing custom plugins.
414 Plugins are loaded using the `--plugin` and `--plugin-dir` options, using
415 either absolute paths or paths relative to the base directory. It is
416 recommended that these options are added directly to the `install` script.
418 See [here][plugins] for a current list of plugins.
420 ## Command-line Arguments
422 Dotbot takes a number of command-line arguments; you can run Dotbot with
423 `--help`, e.g. by running `./install --help`, to see the full list of options.
424 Here, we highlight a couple that are particularly interesting.
426 ### `--only`
428 You can call `./install --only [list of directives]`, such as `./install --only
429 link`, and Dotbot will only run those sections of the config file.
431 ### `--except`
433 You can call `./install --except [list of directives]`, such as `./install
434 --except shell`, and Dotbot will run all the sections of the config file except
435 the ones listed.
437 ## Wiki
439 Check out the [Dotbot wiki][wiki] for more information, tips and tricks,
440 user-contributed plugins, and more.
442 ## Contributing
444 Do you have a feature request, bug report, or patch? Great! See
445 [CONTRIBUTING.md][contributing] for information on what you can do about that.
447 ## License
449 Copyright (c) 2014-2021 Anish Athalye. Released under the MIT License. See
450 [LICENSE.md][license] for details.
452 [PyPI]: https://pypi.org/project/dotbot/
453 [init-dotfiles]: https://github.com/Vaelatern/init-dotfiles
454 [dotfiles-template]: https://github.com/anishathalye/dotfiles_template
455 [inspiration]: https://github.com/anishathalye/dotbot/wiki/Users
456 [managing-dotfiles-post]: http://www.anishathalye.com/2014/08/03/managing-your-dotfiles/
457 [json2yaml]: https://www.json2yaml.com/
458 [plugins]: https://github.com/anishathalye/dotbot/wiki/Plugins
459 [wiki]: https://github.com/anishathalye/dotbot/wiki
460 [contributing]: CONTRIBUTING.md
461 [license]: LICENSE.md