5.5 KiB
flow
flow is a CLI for managing development instances, containers, dotfiles, bootstrap profiles, and
binary packages.
This repository contains the Python implementation of the tool and its command modules.
What is implemented
- Instance access via
flow enter - Container lifecycle commands under
flow dev(create,exec,connect,list,stop,remove,respawn) - Dotfiles management (
dotfiles/dot) - Bootstrap planning and execution (
bootstrap/setup/provision) - Binary package installation from manifest definitions (
package/pkg) - Multi-repo sync checks (
sync)
Installation
Build and install a standalone binary (no pip install required for use):
make build
make install-local
This installs flow to ~/.local/bin/flow.
Configuration
flow uses XDG paths by default:
~/.config/devflow/config~/.config/devflow/manifest.yaml~/.local/share/devflow/~/.local/state/devflow/
config (INI)
[repository]
dotfiles_url = git@github.com:you/dotfiles.git
dotfiles_branch = main
[paths]
projects_dir = ~/projects
[defaults]
container_registry = registry.tomastm.com
container_tag = latest
tmux_session = default
[targets]
# Format A: namespace = platform ssh_host [ssh_identity]
personal = orb personal.orb
# Format B: namespace@platform = ssh_host [ssh_identity]
work@ec2 = work.internal ~/.ssh/id_work
Manifest format
The manifest is YAML with these top-level sections used by the current code:
profilesfor bootstrap profilesbinariesfor package definitionspackage-mapfor cross-package-manager name mapping
environments is no longer supported.
Example:
profiles:
linux-vm:
os: linux
hostname: "$HOSTNAME"
shell: zsh
locale: en_US.UTF-8
requires: [HOSTNAME]
packages:
standard: [git, tmux, zsh, fd]
binary: [neovim]
ssh_keygen:
- type: ed25519
comment: "$USER@$HOSTNAME"
runcmd:
- mkdir -p ~/projects
package-map:
fd:
apt: fd-find
dnf: fd-find
brew: fd
binaries:
neovim:
source: github:neovim/neovim
version: "0.10.4"
asset-pattern: "nvim-{{os}}-{{arch}}.tar.gz"
platform-map:
linux-amd64: { os: linux, arch: x86_64 }
linux-arm64: { os: linux, arch: arm64 }
macos-arm64: { os: macos, arch: arm64 }
install-script: |
curl -fL "{{downloadUrl}}" -o /tmp/nvim.tar.gz
tar -xzf /tmp/nvim.tar.gz -C /tmp
rm -rf ~/.local/bin/nvim
cp /tmp/nvim-*/bin/nvim ~/.local/bin/nvim
Command overview
Enter instances
flow enter personal@orb
flow enter root@personal@orb
flow enter personal@orb --dry-run
If your local terminal uses xterm-ghostty or wezterm, flow enter shows a terminfo warning and
a manual fix command before connecting. flow never installs terminfo on the target automatically.
Containers
flow dev create api -i tm0/node -p ~/projects/api
flow dev connect api
flow dev exec api -- npm test
flow dev list
flow dev stop api
flow dev remove api
Dotfiles
flow dotfiles init --repo git@github.com:you/dotfiles.git
flow dotfiles link
flow dotfiles status
flow dotfiles relink
flow dotfiles clean --dry-run
flow dotfiles repo status
flow dotfiles repo pull --relink
flow dotfiles repo push
Bootstrap
flow bootstrap list
flow bootstrap show linux-vm
flow bootstrap packages --profile linux-vm
flow bootstrap packages --profile linux-vm --resolved
flow bootstrap run --profile linux-vm --var HOSTNAME=devbox
flow bootstrap run --profile linux-vm --dry-run
flow bootstrap auto-detects the package manager (brew, apt, dnf) when
package-manager is not set in a profile.
Packages
flow package install neovim
flow package list
flow package list --all
flow package remove neovim
Sync
flow sync check
flow sync check --no-fetch
flow sync fetch
flow sync summary
Completion
flow completion install-zsh
flow completion zsh
Self-hosted config priority
When present, flow prefers config from a linked dotfiles package:
~/.local/share/devflow/dotfiles/flow/.config/flow/config~/.config/devflow/config
And for manifest:
~/.local/share/devflow/dotfiles/flow/.config/flow/manifest.yaml~/.config/devflow/manifest.yaml
Passing an explicit file path to internal loaders bypasses this cascade.
State format policy
flow currently supports only the v2 dotfiles link state format (linked.json). Older state
formats are intentionally not supported.
CLI behavior
- User errors return non-zero exit codes.
- External command failures are surfaced as concise one-line errors (no traceback spam).
Ctrl+Cexits with code130.
Zsh completion
Recommended one-shot install:
flow completion install-zsh
Manual install (equivalent):
mkdir -p ~/.zsh/completions
flow completion zsh > ~/.zsh/completions/_flow
Then ensure your .zshrc includes:
fpath=(~/.zsh/completions $fpath)
autoload -Uz compinit && compinit
Completion is dynamic and pulls values from your current config/manifest/state (for example
bootstrap profiles, package names, dotfiles packages, and configured enter targets).
Development
Binary build (maintainers):
python3 -m pip install pyinstaller
make build
make install-local
Useful targets:
make clean
Run tests:
python3 -m pytest
Local development setup:
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest