Files
flow/docs/architecture.md

4.3 KiB

Flow Architecture

This document describes the current action-runtime architecture.

Runtime Shape

Flow is organized around a canonical action plan:

cli -> app -> domain -> actions -> adapters

The important boundary is ActionPlan -> ActionExecutor -> ActionResult.

  • cli: Typer command declarations and argument parsing in src/flow/cli.py.
  • app: command use-cases in src/flow/app/. These load config/state, compose domain planners, and submit action plans.
  • domain: pure models, parsers, resolvers, and planners in src/flow/domain/.
  • actions: canonical action models, expansion, execution, dry-run rendering, JSONL audit logging, and rollback in src/flow/actions/.
  • adapters: filesystem, process, git, package-manager, download, archive, container, and tmux implementations in src/flow/adapters/.

The filesystem is not the core abstraction. It is one adapter used by the executor. The core abstraction is the action plan.

Actions

DomainAction captures user intent:

  • kind: dotfiles, package, project, repo, container, remote, setup, or completion
  • action: link, unlink, install, remove, update, pull, push, create, stop, and related verbs
  • payload: typed-by-domain data or already expanded primitive actions
  • rollback_policy: rollbackable, barrier, or none

PrimitiveAction is the executor-owned operation set:

  • filesystem: create/remove symlink, write, write JSON, copy, copy tree, remove, chmod
  • git: clone, pull, push, fetch, checkout, status
  • process: argv command or explicit user shell hook
  • packages/assets: download and archive extraction
  • containers: run, start, stop, kill, remove, exec
  • tmux: new session, set option, respawn pane

Domain actions are expanded before execution. Dry-run output and audit logging come from the same primitive list that real execution uses.

Rollback

Rollback is explicit and best effort.

Supported file/state primitives record reverse actions before mutation. On failure, the executor rolls back in reverse order until it reaches a barrier. External boundaries such as package-manager commands, user shell hooks, git pushes, container lifecycle operations, and interactive command handoffs are not guaranteed to roll back.

Command Surface

Implemented commands:

flow dotfiles init|link|unlink|status|edit
flow dotfiles repos list|status|pull|push
flow packages install|remove|list
flow setup run|show|list
flow remote enter|list
flow enter
flow dev create|attach|connect|exec|enter|stop|remove|rm|respawn|list
flow projects check|fetch|summary
flow sync
flow completion zsh|install-zsh

Global flags:

flow --version
flow --quiet
flow --no-color

Mutating non-interactive commands expose --dry-run where a preview is useful: dotfiles link/unlink, dotfiles repo pull/push, package install/remove, setup run, remote enter, and dev create.

Dotfiles And Modules

The dotfiles repo and _module.yaml repos share one abstraction: managed repos. flow dotfiles repos operates on both. Modules are regular git clones cached under the flow data directory; they are not git submodules.

Link planning treats conflicts and missing modules as pre-execution failures. State is written through actions, and broken tracked symlinks are repaired by the same link reconciliation path.

Packages

Package manifests are parsed into typed dataclasses. Package-manager commands are built as argv lists by the package adapter. Binary and AppImage installs expand into download, archive, copy/chmod, cleanup, post-install barrier, and state-write primitives.

packages remove is strict: it refuses unknown packages, removes tracked files, and writes updated state through the executor.

Tests And Guards

The test suite covers:

  • action executor dry-run, audit logs, rollback, barriers, domain expansion, and primitive dispatch
  • dotfiles discovery, module handling, conflict behavior, rollback, and repo operations
  • package manifest parsing, package-manager argv, binary installs, archive safety, strict removal, and post-install barriers
  • Typer CLI invocation, help output, completion, and error reporting
  • Docker/Podman e2e for the example dotfiles repo when FLOW_RUN_E2E=1

Static guard tests reject direct mutating filesystem and command APIs outside actions, adapters, and tests.