# flow CLI for managing development environments: dotfiles, packages, dev containers, remote targets, and system bootstrap. ## Quick start ```bash make build && make install-local # installs to ~/.local/bin/flow flow setup run linux-work # bootstrap a machine flow dotfiles link # symlink dotfiles flow dev create api -i tm0/node # spin up a dev container flow dev attach api # attach via tmux ``` ## Commands ```bash # Dotfiles flow dotfiles link [--profile NAME] [--dry-run] [--skip PKG...] flow dotfiles unlink [PACKAGES...] [--dry-run] flow dotfiles status [PACKAGES...] flow dotfiles edit PACKAGE [--no-commit] # pull -> $EDITOR -> commit+push # Dotfiles repos (unified: dotfiles repo + module repos) flow dotfiles repos list flow dotfiles repos status [--repo NAME] flow dotfiles repos pull [--repo NAME] [--dry-run] flow dotfiles repos push [--repo NAME] [--dry-run] # Packages flow packages install [NAMES...] [--profile NAME] [--dry-run] flow packages remove NAMES... flow packages list [--all] # Bootstrap flow setup run PROFILE [--dry-run] # run a full bootstrap profile flow setup show PROFILE # preview profile steps flow setup list # Remote targets flow remote enter TARGET [--dry-run] # ssh + tmux into a remote target flow remote list # Dev containers (docker or podman) flow dev create NAME -i IMAGE [-p PROJECT] [--dry-run] flow dev attach NAME # tmux session into container flow dev exec NAME [-- CMD...] # run a command in container flow dev enter NAME # interactive shell flow dev stop NAME [--kill] flow dev remove NAME [-f] flow dev respawn NAME # restart all tmux panes flow dev list # Projects flow projects check [--fetch] # scan ~/projects for dirty repos flow projects fetch # fetch all project remotes flow projects summary # quick overview # Shell completion flow completion zsh # print zsh completion script flow completion install-zsh # install to ~/.zsh/completions # Global flags flow --version flow --quiet # suppress info output flow --no-color # disable colored output ``` ### Aliases - `dotfiles` -> `dot` - `dotfiles repos` -> `dotfiles repo` - `packages` -> `package`, `pkg` - `projects` -> `project`, `sync` (with `--fetch` default) - `setup` -> `bootstrap` - `dev attach` -> `dev connect` - `dev remove` -> `dev rm` ## Configuration Loaded from `~/.config/flow/config.yaml`, merged with dotfiles repo overlay at `~/.local/share/flow/dotfiles/_shared/flow/.config/flow/`. ```yaml repository: url: git@github.com:you/dotfiles.git branch: main paths: projects: ~/projects defaults: container-runtime: auto # auto | docker | podman | podman-rootful container-registry: registry.example.com container-tag: latest tmux-session: main targets: personal@orb: personal.orb work@ec2: host: work.ec2.internal identity: ~/.ssh/id_work ``` ### Container runtime `container-runtime` controls which engine `flow dev` uses: - `auto` -- detect docker or podman from PATH (default) - `docker` -- force docker - `podman` -- force podman, prefer rootless socket - `podman-rootful` -- force podman, prefer rootful socket (`/run/podman/podman.sock`) When using podman, `flow dev create` automatically adds `--security-opt label=disable` for engine socket access. The socket is always mounted to `/var/run/docker.sock` inside the container (Podman's Docker-compatible API). ## 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 `_module.yaml` inside a package mounts an external git repo at that location: ```yaml source: github:org/nvim-config ref: branch: main ``` Modules are regular git clones managed by flow (not git submodules). They appear alongside the dotfiles repo in `flow dotfiles repos list` and are pulled/pushed with the same commands. ## Manifest Packages and profiles defined in YAML files under the flow config directory. ```yaml 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" ``` ## Architecture Four layers: **core** (runtime primitives, config, errors) -> **domain** (pure functions, frozen dataclasses) -> **services** (I/O orchestration) -> **commands** (thin CLI adapters). Core primitives (`SystemRuntime`): `CommandRunner`, `FileSystem`, `GitClient`, `TmuxClient`, `ContainerRuntime`. ## Security - Rejects root invocation - `_root/` dotfile paths require sudo for linking - Package post-install hooks run without sudo by default ## Development ```bash make deps # create .venv + install deps .venv/bin/python -m pytest tests/ -v # run tests ```