- Makefile gains `test` and `test-e2e` targets; `deps` now installs the dev extras so pytest is available after `make deps`. - .github/workflows/test.yml runs unit tests on push and PR to main (Python 3.13 on ubuntu-latest, ignores tests/e2e by default). - tests/e2e/Containerfile + test_dotfiles_e2e.py scaffold a real container-based smoke test of `flow dotfiles init` + `link` against the example dotfiles repo. Gated by FLOW_RUN_E2E=1 so unit runs stay fast; verified locally with podman. - tests/fakes.FakeRunner uses ordered subsequence matching instead of unordered containment -- prevents accidental match between unrelated commands that happen to share tokens. - example/README.md rewritten for the current command surface (no more `dotfiles undo`, `dotfiles modules ...`, `--relink`, `bootstrap list/show/run --profile`, `bootstrap packages --resolved`). Adds an "External modules" section documenting `_module.yaml`. - example/dotfiles-repo profiles.yaml drops `allow-sudo: true` along with the runtime support. - pyproject.toml adds [tool.coverage] config. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Example working scenario
This folder contains a complete dotfiles + setup configuration for the current flow schema.
What this example shows
- Flat repo-root layout with reserved dirs:
_shared/(shared configs)- profile dirs (
linux-auto/,macos-dev/) - package-local
_root/marker for root-targeted files
- Unified YAML config under
_shared/flow/.config/flow/*.yaml - Profile package list syntax: string, type prefix, and object entries
- Binary install definition with
asset-pattern,platform-map,extract-dir, andinstall - Required env vars, templating, SSH keygen, runcmd, post-link, and config skip patterns
Layout
dotfiles-repo/_shared/flow/.config/flow/config.yamldotfiles-repo/_shared/flow/.config/flow/packages.yamldotfiles-repo/_shared/flow/.config/flow/profiles.yamldotfiles-repo/_shared/...dotfiles-repo/linux-auto/...dotfiles-repo/macos-dev/...
Quick start
Use the absolute path to this local example repo:
EXAMPLE_REPO="/ABSOLUTE/PATH/TO/flow-cli/example/dotfiles-repo"
Initialize and link dotfiles:
flow dotfiles init --repo "$EXAMPLE_REPO"
flow dotfiles link --profile linux-auto
flow dotfiles status
flow dotfiles unlink # remove all managed symlinks
flow dotfiles unlink git tmux # remove only specific packages
Manage the dotfiles and any module repos as a unified set:
flow dotfiles repos list
flow dotfiles repos status
flow dotfiles repos pull
flow dotfiles repos push
Edit a package or a specific file under the dotfiles repo:
flow dotfiles edit git --no-commit
flow dotfiles edit _shared/flow/.config/flow/profiles.yaml --no-commit
Inspect setup profiles and run a setup:
flow setup list
flow setup show linux-auto
flow setup run linux-auto \
--var TARGET_HOSTNAME=devbox \
--var USER_EMAIL=you@example.com \
--dry-run
flow setup run macos-dev --dry-run
bootstrap and provision remain as aliases for setup, so flow bootstrap run linux-auto still works.
Install or list packages directly (independent of a setup run):
flow packages list
flow packages list --all
flow packages install --profile linux-auto --dry-run
flow packages install fd ripgrep --dry-run
flow packages remove docker --dry-run
External modules
A package directory inside the dotfiles repo can pull its contents from a separate
git repository by placing a _module.yaml file at the package root. Flow clones
the module into a shared cache and links from the cached path, so updates flow
through flow dotfiles repos pull.
This example does NOT include a real _module.yaml (it would pin the example to
a flaky external dependency). For reference, a hypothetical nvim/_module.yaml
would look like:
# example/dotfiles-repo/nvim/_module.yaml (not committed -- format reference only)
source: github:your-org/nvim-config # or a full git URL
ref:
branch: main # exactly one of: branch, tag, commit
After adding such a file, the next flow dotfiles repos pull will clone the
module and flow dotfiles link --profile linux-auto will link its contents.