Flow Example
example/ is a single complete fixture for the current flow schema. It contains
one dotfiles repository plus one local module repository, showcasing shared
dotfiles, profile-specific dotfiles, package definitions, setup profiles,
root-targeted files, external modules, templates, and shell hooks.
Layout
example/
dotfiles-repo/
_shared/
_root/etc/hostname
_root/usr/local/bin/custom-script.sh
bin/.local/bin/flow-hello
flow/.config/flow/config.yaml
flow/.config/flow/packages.yaml
flow/.config/flow/profiles.yaml
git/.gitconfig
nvim/.config/nvim/_module.yaml
tmux/.tmux.conf
zsh/.zshrc
linux-auto/
ssh/.ssh/config
macos-dev/
ghostty/.config/ghostty/config
module-repos/
nvim-config/
init.lua
lua/plugins.lua
The fixture demonstrates:
_shared/plus profile-specific layers_root/absolute-path planning for sudo-backed links_module.yamlexternal module planning with a local module repository- flow config and manifest overlay under
_shared/flow/.config/flow - package-manager, cask, and binary package definitions
- profile package shorthand and object overrides
- required env vars, templating, SSH key generation,
runcmd,post-link, and config skip patterns
Try It Safely
Use a temporary HOME/XDG sandbox so the example cannot touch your real dotfiles.
dotfiles init clones with git, so first copy the fixture into a temporary git
repo:
DEMO="$(mktemp -d)"
mkdir -p "$DEMO/home"
cp -a example/dotfiles-repo "$DEMO/dotfiles-src"
cp -a example/module-repos "$DEMO/module-repos"
git -C "$DEMO/module-repos/nvim-config" init -q -b main
git -C "$DEMO/module-repos/nvim-config" config user.email e2e@example.com
git -C "$DEMO/module-repos/nvim-config" config user.name "flow example"
git -C "$DEMO/module-repos/nvim-config" add -A
git -C "$DEMO/module-repos/nvim-config" commit -q -m initial
git -C "$DEMO/dotfiles-src" init -q -b main
git -C "$DEMO/dotfiles-src" config user.email e2e@example.com
git -C "$DEMO/dotfiles-src" config user.name "flow example"
git -C "$DEMO/dotfiles-src" add -A
git -C "$DEMO/dotfiles-src" commit -q -m initial
cd "$DEMO"
Run flow against that sandbox:
HOME="$DEMO/home" \
XDG_CONFIG_HOME="$DEMO/config" \
XDG_DATA_HOME="$DEMO/data" \
XDG_STATE_HOME="$DEMO/state" \
uv run flow dotfiles init --repo "$DEMO/dotfiles-src"
HOME="$DEMO/home" \
XDG_CONFIG_HOME="$DEMO/config" \
XDG_DATA_HOME="$DEMO/data" \
XDG_STATE_HOME="$DEMO/state" \
uv run flow dotfiles link --profile linux-auto --skip _root --dry-run
HOME="$DEMO/home" \
XDG_CONFIG_HOME="$DEMO/config" \
XDG_DATA_HOME="$DEMO/data" \
XDG_STATE_HOME="$DEMO/state" \
uv run flow dotfiles link --profile linux-auto --skip _root
--skip _root avoids root-targeted paths such as /etc/hostname during the demo.
Useful follow-up commands:
HOME="$DEMO/home" XDG_CONFIG_HOME="$DEMO/config" XDG_DATA_HOME="$DEMO/data" XDG_STATE_HOME="$DEMO/state" uv run flow dotfiles status
HOME="$DEMO/home" XDG_CONFIG_HOME="$DEMO/config" XDG_DATA_HOME="$DEMO/data" XDG_STATE_HOME="$DEMO/state" uv run flow dotfiles repos list
HOME="$DEMO/home" XDG_CONFIG_HOME="$DEMO/config" XDG_DATA_HOME="$DEMO/data" XDG_STATE_HOME="$DEMO/state" uv run flow setup list
HOME="$DEMO/home" XDG_CONFIG_HOME="$DEMO/config" XDG_DATA_HOME="$DEMO/data" XDG_STATE_HOME="$DEMO/state" uv run flow setup show linux-auto
HOME="$DEMO/home" XDG_CONFIG_HOME="$DEMO/config" XDG_DATA_HOME="$DEMO/data" XDG_STATE_HOME="$DEMO/state" uv run flow packages install --profile linux-auto --dry-run
Remove the sandbox when done:
rm -rf "$DEMO"
External Modules
A package directory may mount a separate git repo by adding _module.yaml
under the desired mount path:
source: module-repos/nvim-config
ref:
branch: main
The example nvim package mounts example/module-repos/nvim-config at
.config/nvim. Flow implements modules through _module.yaml; it does not
implement a top-level _modules/ dotfiles layout convention. flow dotfiles repos pull clones or updates module caches, and flow dotfiles link links
from those caches.