1 unstable release
new 0.6.1 | Apr 26, 2025 |
---|
#7 in #dotfiles-manager
120KB
2.5K
SLoC
OCD
Organize current dotfiles.
This tool provides a way to manage the user's dotfiles through a cluster. A cluster is a group of repositories that can be deployed together. Upon deployment, the user can issue Git commands interactively to manage their dotfiles within a given repository apart of their cluster.
A cluster is comprised of two basic repository entries: root and node. Both of these entry types can either be normal or bare-alias. A normal repository entry is just a regular Git repository whose gitdir and worktree point to the same path. A bare-alias repository entry is a bare Git repository that uses an external directory as an alias for a worktree.
The root of a cluster is a special bare-alias repository that contains the
cluster definition itself, i.e. the special cluster.toml
file that describes
all entries apart of the user's cluster. There can only exist one root, and it
is always deployed such that it cannot be undeployed. Removal of the root
repository will cause the entire cluster to be removed at once.
The nodes of a cluster are the various repositories containing dotfile configurations. A given node can either be defined as normal or bare-alias. Any node can be added, removed, deployed, or undeployed from a cluster at any time through OCD's command-set.
Installation
Make sure you have the following pieces of software already installed before attempting to install OCD itself:
Through Cargo simply type the following into your terminal:
cargo install ocd --locked
Currently, there are no packaged version of OCD for major Linux distributions, but hopefully that will change as OCD becomes more mature. Finally, you can also directly build the project yourself by cloning and using Cargo.
Usage
First things first, initialize a new root repository like so:
ocd init --root
The above will create a new root for your cluster. Root is a special bare-alias
repository that contains the cluster definition, i.e., special configuration
file located at $XDG_CONFIG_HOME/ocd/cluster.toml
. This repository is always
deployed such that it cannot be undeployed. Without it OCD will not know how
to manage your cluster.
Lets assume that you want to configure dotfiles for Bash shell as an example. Initialize a new repository named bash:
ocd init --home-alias bash
The command above will initialize a bare-alias repository named "bash" in your repository store, and will set the default directory alias to your home directory in your cluster definition. You should see the following in your cluster definition:
[nodes.bash]
deployment = "bare_alias"
url = ""
The above is called a node entry, or node. A node provides various settings that help OCD determine how to treat a given repository in your repository store. For now you only have "root" and "bash" as entries in your repository store.
Lets assume that you have a remote already setup to push changes. So fill in
the url
field above with the URL of that remote repository:
[nodes.bash]
deployment = "bare_alias"
url = "https://github.com/user/bash.git"
Now assume that you already have written the following files to stage and commit into the "bash" node in your home directory, and your current working directory is your home directory:
- A
.bashrc
file. - A
.bash_profile
file. - A
README.md
file.
To add these files, simply issue Git commands through OCD by using the name of the repository you want to issue those commands to like so:
ocd "bash" remote add origin https://github.com/user/bash.git
ocd "bash" add .bashrc .bash_profile README.md
ocd "bash" commit -m "Initial commit"
ocd "bash" push -u origin main
If you want to issue Git commands to multiple Git repositories you can use unit-like matching patterns, and comma separated lists. For example:
ocd "*sh,foo,bar" remote add origin https://github.com/user/bash.git
ocd "b?sh" add .bashrc .bash_profile README.md
ocd "[a-b]?sh, ?oo, *ar" commit -m "Initial commit"
ocd "root,*" push -u origin main
If you want to issue Git commands to your root repository, then you need to spell out root in full:
ocd "root" status
The separation of root from nodes of your cluster is mainly done to make it a little harder to shoot yourself in the foot. It is recommended that you should always use quotes around patterns you wish to use to match repositories to issue commands upon.
Moving on, lets take advantage of the file exclusion feature that OCD offers
upon deployment of a given repository. You may not always want that README.md
file to always be deployed, so add this to your cluster definition:
[nodes.bash]
deployment = "bare_alias"
url = "https://github.com/user/bash.git"
excluded = ["README*"]
You can also use "README.md", but the excluded
field accepts gitignore-style
patterns for excluding files from deployment. Now undeploy the excluded files of
"bash" like so:
ocd undeploy --excluded-only "bash"
Now only .bashrc
and .bash_profile
should be deployed, with README.md
undeployed. You can bring back README.md
using the deploy
command:
ocd deploy --with-excluded "bash"
Okay, now assume that you want to use an external repository to configure your PS1 in bash. Lets use https://github.com/agkozak/polyglot for this. Go into your cluster definition and add the following:
[nodes.bash]
deployment = "bare_alias"
url = "https://github.com/user/bash.git"
excluded = ["README*"]
dependencies = ["polyglot_prompt"]
[nodes.polyglot_prompt]
deployment = { kind = "bare_alias", dir_alias = "$HOME/.local/share"
url = "https://github.com/agkozak/polyglot.git"
excluded = [
".github/",
"img/",
".gitignore",
".vimrc.local",
"LICENSE",
"README.md",
"polyglot.plugin.zsh"
]
The above showcases an extended form of the deployment
field for the
"polyglot_prompt" node. This is how the field is supposed to be written in
full. In fact, the deployment = "bare\_alias"
field in "bash" is just
syntactic sugar for:
deployment = { kind = "bare\_alias", dir\_alias = "$HOME" }
The excluded
field for "polyglot_prompt" essentially ignores most of its
worktree except for "polyglot.sh", which will be deployed to
$HOME/.local/share"
.
Finally, we specify that "polyglot_prompt" as dependency of "bash" through the
dependencies
field. Now if we use the following command like so:
ocd deploy "bash"
The "bash" node will be deployed, along with "polyglot_prompt". The deploy command will automatically clone "polyglot_prompt" into the repository store, and deploy it.
Finally, assume that you have staged and committed all changes to your root repository to a remote like so:
ocd "root" remote add origin https://github.com/user/dots-root.git"
ocd "root" add "$XDG_CONFIG_HOME/ocd/*"
ocd "root" commit -m "Initial commit"
ocd "root" push -u origin main
Now you want to transfer your cluster to a different machine. All you have to do is use OCD's clone command:
ocd clone https://github.com/user/dots-root.git
This will clone your root repository and deploy it. Afterwards, this command will clone all nodes of your repository asynchronously into your repository store on the new machine.
Given that you only have access to one root at any given time per cluster. If
you want to use a new cluster configuration, when you already have an existing
cluster on your machine, you can simply use the rm
command to nuke your
cluster like so:
ocd rm "root"
You will be prompted about really doing this. If you accept, all nodes (including root) will be undeployed, and the configuration directory and repository store will be removed in one-shot recursively.
You can just use the rm
command to remove regular nodes from your cluster,
e.g., ocd rm "bash"
or something similar. This will just remove the node from
your cluster configuration and repository store.
Finally, you can list all entries in your cluster with some fancy status
information using the ls
command:
ocd ls
Use the help
command, or --help
flag to get more information about using
OCD, or a given OCD command.
Enjoy!
Contribution
The OCD coding project is open to contribution.
See the contribution guidelines for more information about contributing to the project.
License
The OCD project abides by the MIT license for distribution of its source code and documentation. The project also uses the CC0-1.0 license to place files in the public domain, which are considered to be to small, or to generic to place copyright over.
The project uses the REUSE 3.3 specification to make it easier to determine who owns the copyright and licensing of any given file in the codebase. The Developer Certificate of Origin version 1.1 is also used to ensure that any contributions made have the right to be merged into the project, and can be distributed with the project under its main licenses.
Dependencies
~27–37MB
~608K SLoC