24d682adf1393dab162e93a7431127abf2bb8ca5
flow
flow is a CLI for managing development instances, containers, dotfiles, and host bootstrap.
What is implemented
- Instance access via
flow enter - Container lifecycle under
flow dev - Dotfiles repo management (
flow dotfiles) - Bootstrap provisioning (
flow bootstrap) - Package installs from unified manifest definitions (
flow package) - Project sync checks (
flow sync)
Installation
make build
make install-local
This installs flow to ~/.local/bin/flow.
Core behavior
Security model
flowmust run as a regular user (root/sudo invocation is rejected).- At startup,
flowrefreshes sudo credentials once (sudo -v) for privileged steps. - Package
post-installhooks run without sudo by default. - A package hook can use sudo only when
allow_sudo: trueis explicitly set.
Config location and merge rules
flow loads all YAML files from:
~/.local/share/flow/dotfiles/_shared/flow/.config/flow/(self-hosted, if present)~/.config/flow/(local fallback)
Files are read alphabetically (*.yaml and *.yml) and merged at top level.
If the same top-level key appears in multiple files, the later filename wins.
repository.pull-before-edit controls whether flow dotfiles edit runs git pull --rebase first (default: true).
When pull brings new changes, flow shows an info message and waits for Enter before opening the editor.
Dotfiles layout (flat with reserved dirs)
Inside your dotfiles repo root:
_shared/
flow/
.config/flow/
config.yaml
packages.yaml
profiles.yaml
dnsmasq/
.user_hosts
_root/
opt/homebrew/etc/dnsmasq.conf
git/
.gitconfig
linux-auto/
nvim/
.config/nvim/init.lua
_shared/: linked for all profiles_root/is a marker inside a package for absolute paths (via sudo), e.g.dnsmasq/_root/etc/hostname -> /etc/hostname- every other directory at this level is a profile name
- any target conflict fails (including
_sharedvs profile)
External module packages
Packages can be backed by an external git repository using _module.yaml:
source: github:org/nvim-config
ref:
branch: main
- If a package directory contains
_module.yaml, flow uses the fetched module content as package source. - Any sibling files in that package directory are ignored (shown only in
--verbose). - Modules are refreshed on
flow dotfiles initandflow dotfiles sync(not onlink).
Manifest model
Top-level keys:
profilespackages- optional global settings like
repository,paths,defaults,targets
environments is not supported.
Packages (unified)
packages:
- name: fd
type: pkg
sources:
apt: fd-find
dnf: fd-find
brew: fd
- name: wezterm
type: cask
sources:
brew: wezterm
- name: neovim
type: binary
source: github:neovim/neovim
version: "0.10.4"
asset-pattern: "nvim-{{os}}-{{arch}}.tar.gz"
platform-map:
linux-x64: { os: linux, arch: x64 }
linux-arm64: { os: linux, arch: arm64 }
darwin-arm64: { os: macos, arch: arm64 }
extract-dir: "nvim-{{os}}64"
install:
bin: [bin/nvim]
share: [share/nvim]
man: [share/man/man1/nvim.1]
lib: [lib/libnvim.so]
Profile package syntaxes
All are supported in one profile list:
profiles:
macos-dev:
os: macos
packages:
- git
- cask/wezterm
- binary/neovim
- name: docker
allow_sudo: true
post-install: |
sudo groupadd docker || true
sudo usermod -aG docker $USER
Templates
{{ env.VAR_NAME }}{{ version }}{{ os }}{{ arch }}
Bootstrap profile features
osis required (linuxormacos)package-manageroptional (auto-detected if omitted)- default locale is
en_US.UTF-8 - shell auto-install +
chshwhenshell:is declared and missing requiresvalidation for required env varsssh-keygendefinitionsruncmd(runs after package installation)- automatic config linking (
_shared+ profile, including package-local_rootmarkers) post-linkhook (runs after symlink phase)- config skip patterns:
- package names (e.g.
nvim) _shared_profile_root
- package names (e.g.
Command overview
flow enter personal@orb
flow dev create api -i tm0/node -p ~/projects/api
flow dotfiles init --repo git@github.com:you/dotfiles.git
flow dotfiles link --profile linux-auto
flow dotfiles undo
flow dotfiles status
flow dotfiles modules list
flow dotfiles modules sync
flow bootstrap list
flow bootstrap show linux-auto
flow bootstrap run --profile linux-auto --var USER_EMAIL=you@example.com
flow package install neovim
flow package list --all
flow sync check
flow completion install-zsh
Development
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
python3 -m pytest
FLOW_RUN_E2E_CONTAINER=1 .venv/bin/pytest -q tests/test_dotfiles_e2e_container.py
Description
Languages
Python
99%
Makefile
0.9%