# 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): ```bash 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) ```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 two top-level sections used by the current code: - `profiles` for bootstrap profiles - `binaries` for package definitions `environments` is no longer supported. Example: ```yaml profiles: linux-vm: os: linux hostname: "$HOSTNAME" shell: zsh locale: en_US.UTF-8 requires: [HOSTNAME] packages: standard: [git, tmux, zsh] binary: [neovim] ssh_keygen: - type: ed25519 comment: "$USER@$HOSTNAME" runcmd: - mkdir -p ~/projects 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 ```bash flow enter personal@orb flow enter root@personal@orb flow enter personal@orb --dry-run ``` ### Containers ```bash 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 ```bash flow dotfiles init --repo git@github.com:you/dotfiles.git flow dotfiles link flow dotfiles status flow dotfiles relink flow dotfiles clean --dry-run ``` ### Bootstrap ```bash flow bootstrap list flow bootstrap show linux-vm flow bootstrap run --profile linux-vm --var HOSTNAME=devbox flow bootstrap run --profile linux-vm --dry-run ``` ### Packages ```bash flow package install neovim flow package list flow package list --all flow package remove neovim ``` ### Sync ```bash flow sync check flow sync check --no-fetch flow sync fetch flow sync summary ``` ### Completion ```bash flow completion install-zsh flow completion zsh ``` ## Self-hosted config priority When present, `flow` prefers config from a linked dotfiles package: 1. `~/.local/share/devflow/dotfiles/flow/.config/flow/config` 2. `~/.config/devflow/config` And for manifest: 1. `~/.local/share/devflow/dotfiles/flow/.config/flow/manifest.yaml` 2. `~/.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+C` exits with code `130`. ## Zsh completion Recommended one-shot install: ```bash flow completion install-zsh ``` Manual install (equivalent): ```bash mkdir -p ~/.zsh/completions flow completion zsh > ~/.zsh/completions/_flow ``` Then ensure your `.zshrc` includes: ```bash 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): ```bash python3 -m pip install pyinstaller make build make install-local ``` Useful targets: ```bash make clean ``` Run a syntax check: ```bash python3 -m compileall . ``` Run tests (when `pytest` is available): ```bash python3 -m pytest ``` Optional local venv setup: ```bash python3 -m venv .venv .venv/bin/pip install -U pip pytest pyyaml PYTHONPATH=/path/to/src .venv/bin/pytest ```