2026-02-13 09:57:38 +02:00
2026-02-13 09:57:38 +02:00
2026-02-13 09:57:38 +02:00
2026-02-13 09:57:38 +02:00
wip
2026-02-13 02:13:27 +02:00
2026-02-13 09:57:38 +02:00
wip
2026-02-13 02:13:27 +02:00
wip
2026-02-13 02:13:27 +02:00
2026-02-13 09:57:38 +02:00

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:

  • profiles for bootstrap profiles
  • binaries for package definitions
  • package-map for 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:

  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:

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
Description
No description provided
Readme 329 KiB
Languages
Python 99%
Makefile 0.9%