File Format
Dotkit files come in two formats that produce identical shell output. Use whichever fits your workflow: plain text is terse and script-like, Markdown renders as readable documentation on GitHub.
Plain .sh files in a run folder are sourced directly with no parsing.
.txt format
Section titled “.txt format”Blocks are separated by --- on its own line. The first non-blank, non-comment line of each block sets its type. Lines beginning with # are comments.
# This is a comment
try command -v brewNONINTERACTIVE=1dotkit install https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh---map brew install {{item}}ghripgrepneovim---ask Restart terminal?exec zsh -l.md format
Section titled “.md format”## headers open blocks. The heading verb sets the block type. Top-level bullets (- ) are commands or data. Everything else (H1 headers, prose, nested bullets, blockquotes) is documentation and ignored.
# Homebrew & Formulae
This installs Homebrew if missing, then installs formulae.
## try
- command -v brew- dotkit install [install.sh](https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)
## map
- brew install **item**- gh- ripgrep- neovim
## ask
- Restart terminal?- exec zsh -lIn the .md format, substitution markers use **word** instead of {{word}} so the file renders as valid Markdown. The parser converts **item** → {{item}} before processing.
Markdown links ([label](url)) are converted to bare URLs. This lets you write readable link text while the parser uses the URL.
Block types
Section titled “Block types”try - conditional execution
Section titled “try - conditional execution”The body runs only if the check command exits non-zero. Use it to skip installation when a tool is already present.
try command -v brewNONINTERACTIVE=1dotkit install https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh## try
- command -v brew- dotkit install [install.sh](https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)Compiles to:
command -v brew || { NONINTERACTIVE=1 dotkit install https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh}map - template over data
Section titled “map - template over data”Runs a template command once per data row, substituting placeholders. Empty lines and comment lines in the data are skipped.
map brew install {{item}}ghripgrepneovim## map
- brew install **item**- gh- ripgrep- neovimSubstitutions
Section titled “Substitutions”Data rows split on = (space-padded equals) into positional fields:
| Placeholder | Alias | Value |
|---|---|---|
{{1}} | {{item}}, {{key}} | First field |
{{2}} | {{value}} | Second field |
{{3}} | N/A | Third field |
Single-field rows (no =) fill {{1}} / {{item}} / {{key}}.
Key-value example:
map git config --global {{key}} {{value}}user.name = Your Nameuser.email = [email protected]init.defaultBranch = main## map
- git config --global **key** **value**- user.name = Your Name- user.email = [email protected]- init.defaultBranch = mainThree-field example:
map git clone [email protected]:{{1}}/{{2}}.git ~/dev/{{3}}yourname = dotkit = dotkityourname = dotfiles = dotfilesask - interactive prompts
Section titled “ask - interactive prompts”Three variants depending on the message and whether a body is present:
Pause - print message and wait for Enter (no body):
ask Restart your terminal to apply PATH changes## ask
- Restart your terminal to apply PATH changesYes/no - run body only if user answers yes:
ask Install Mac App Store apps?mas install 497799835mas install 310633997## ask
- Install Mac App Store apps?- mas install 497799835- mas install 310633997Input capture - prompt for hidden input, store in a variable:
ask $GITHUB_TOKEN GitHub personal access tokengh auth login --with-token <<< "$GITHUB_TOKEN"## ask
- $GITHUB_TOKEN GitHub personal access token- gh auth login --with-token <<< "$GITHUB_TOKEN"Input is hidden (stty -echo). Suited for tokens and passwords.
Plain shell
Section titled “Plain shell”Any block whose first content line doesn’t start with try, map, or ask is treated as plain shell and passed through verbatim.
echo "Configuring git..."git config --global core.excludesfile ~/.gitignore_globalgit config --global push.autoSetupRemote true## run
- echo "Configuring git..."- git config --global core.excludesfile ~/.gitignore_global- git config --global push.autoSetupRemote trueIn .md, use ## run to mark a plain-shell block explicitly. Any unrecognized ## heading also produces a plain-shell block.
Mixing blocks
Section titled “Mixing blocks”A single file can have any number of blocks in any order:
# Install Homebrew if missingtry command -v brewNONINTERACTIVE=1dotkit install https://raw.githubusercontent.com/Homebrew/install/HEAD/install.shfor p in /opt/homebrew /usr/local ~/.linuxbrew; do eval "$($p/bin/brew shellenv 2>/dev/null)" 2>/dev/null || truedone---# Tapsmap brew tap {{item}}hashicorp/tap---# Formulaemap brew install {{item}}ghripgrepterraform---# Casksmap brew install --cask {{item}}firefoxvisual-studio-codeghostty