Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
flow
flow is a CLI for managing development environments: dotfiles, packages, containers, remote targets, and system bootstrap.
Installation
make build
make install-local
This installs flow to ~/.local/bin/flow.
Architecture
Four-layer design: core (runtime, config, errors) -> domain (pure functions, frozen dataclasses) -> services (I/O orchestration) -> commands (thin CLI adapters).
- Domain layer is pure: no I/O, no side effects, fully testable
- Services perform all I/O and delegate logic to domain functions
- Commands are trivial dispatchers from argparse to services
Commands
# Dotfiles
flow dotfiles link [--profile NAME] [--dry-run] [--skip PKG...]
flow dotfiles unlink [PACKAGES...] [--dry-run]
flow dotfiles status
flow dotfiles sync
# Packages
flow packages install [NAMES...] [--profile NAME] [--dry-run]
flow packages remove NAMES... [--dry-run]
flow packages list
# Bootstrap
flow setup run PROFILE [--dry-run]
flow setup show PROFILE
flow setup list
# Remote targets
flow remote enter NAMESPACE@PLATFORM [--dry-run]
flow remote list
# Dev containers
flow dev create IMAGE [--namespace NS] [--dry-run]
flow dev enter NAME [--shell PATH]
flow dev stop NAME
flow dev remove NAME
flow dev list
# Projects
flow projects check [--fetch]
# Other
flow --version
flow --quiet
flow completion
Configuration
Config is loaded from ~/.config/flow/config.yaml and merged with self-hosted config from the dotfiles repo at ~/.local/share/flow/dotfiles/_shared/flow/.config/flow/.
repository:
url: git@github.com:you/dotfiles.git
branch: main
paths:
projects: ~/projects
defaults:
container-registry: registry.example.com
tmux-session: main
targets:
personal@orb: personal.orb
work@ec2:
host: work.ec2.internal
identity: ~/.ssh/id_work
Dotfiles layout
_shared/ # Linked for all profiles
zsh/
.zshrc
nvim/
.config/nvim/
_module.yaml # External git module
.local/bin/
nvim-wrapper
dns/
_root/ # Absolute path marker (needs sudo)
etc/hosts
linux-work/ # Profile-specific layer
i3/
.config/i3/config
External modules
A _module.yaml inside a package mounts an external git repo at that location:
source: github:org/nvim-config
ref:
branch: main
Module files are linked from the clone cache, while local files outside the mount path are linked from the dotfiles repo.
Manifest
Packages and profiles are defined in YAML files under the flow config directory.
packages:
- name: fd
type: pkg
sources:
apt: fd-find
brew: fd
- name: neovim
type: binary
source: github:neovim/neovim
version: "0.10.4"
platform-map:
linux-x64: nvim-linux-x86_64.tar.gz
profiles:
linux-work:
os: linux
hostname: dev-box
locale: en_US.UTF-8
shell: zsh
packages:
- fd
- binary/neovim
ssh-keys:
- path: ~/.ssh/id_ed25519
type: ed25519
runcmd:
- echo "setup complete"
Security
flowmust run as a regular user (root invocation is rejected)_root/files require sudo for linking- Package post-install hooks run without sudo by default
Development
make deps
.venv/bin/python -m pytest tests/ -v