7.6 KiB
Flow CLI Refactor Status
Based on code review (2026-03-22), architecture discussion, and the current implementation. Spec:
docs/superpowers/specs/2026-03-16-flow-architecture-redesign.md
Current State
The action-runtime rewrite is implemented. cli.py is a thin Typer adapter, flow.app owns
application orchestration, domain modules keep pure planning and resolution logic, and
executor-managed mutations are represented as action plans before they reach runtime adapters.
The old structural problems from the original codebase (duplicated flows, monkeypatching, dead modules, singleton-style runtime access) have been removed from the active command paths. The remaining refactor work is deferred cleanup, not a blocker for the action-centered architecture.
Command Surface
This is the implemented command surface.
flow remote enter <target> # Host only. SSH+tmux into VM.
flow remote list # List configured targets.
flow dev create <name> -i <image> # VM only. Create+start container.
flow dev attach <name> # Attach to container tmux session.
flow dev exec <name> [cmd...] # Run command in container.
flow dev enter <name> # Interactive shell in container.
flow dev list # List dev containers.
flow dev stop <name> # Stop container.
flow dev rm <name> # Remove container.
flow dev respawn <name> # Respawn tmux panes.
flow dotfiles init --repo <url> # Clone dotfiles repo + all module repos.
flow dotfiles link [--profile p] # Reconcile symlinks (creates, fixes broken, removes stale).
flow dotfiles unlink [packages...] # Remove managed symlinks.
flow dotfiles status [packages...] # Show packages, link health, module info.
flow dotfiles edit <package> # Pull -> $EDITOR -> commit+push.
flow dotfiles repos list # List ALL managed repos (dotfiles + modules).
flow dotfiles repos status [--repo=x] # Git status for one or all repos.
flow dotfiles repos pull [--repo=x] [--dry-run]
flow dotfiles repos push [--repo=x] [--dry-run]
flow setup run [profile|--profile p] [--dry-run] [--var KEY=VALUE]
flow setup list # List profiles.
flow setup show <profile> # Show profile plan.
flow packages install [name...] [--profile p] [--dry-run]
flow packages list [--all] # List packages.
flow packages remove <name...> [--dry-run]
flow projects check [--fetch] # VM only. Git health across ~/projects.
flow projects fetch # Fetch all project remotes.
flow projects summary # Quick status overview.
Aliases
dotfiles->dotpackages->package,pkgprojects->project;flow sync->flow projects check --fetchsetup->bootstrap,provisionremote enter->enterdev attach->dev connectdev rm->dev removedotfiles repos->dotfiles repo
Global flags
--version--quiet/-q--no-color
Commands Removed During Refactor
| Removed | Reason |
|---|---|
dotfiles sync |
Redundant: repos pull + link |
dotfiles relink |
Redundant: link is idempotent |
dotfiles undo |
Redundant: unlink is the inverse of link |
dotfiles clean |
Folded into link (reconciliation handles broken symlinks) |
dotfiles modules list |
Replaced by dotfiles repos list |
dotfiles modules sync |
Replaced by dotfiles repos pull |
Action-Centered Architecture
The runtime boundary is flow.actions.
ActionPlanis the unit of execution. It can contain high-levelDomainActionentries and directPrimitiveActionentries.DomainActionrecords intent from a domain such as dotfiles, packages, repos, remote targets, containers, completion, or setup.expand_actions()converts domain actions into primitive actions. Some domains supply already expanded primitive plans when the service has concrete runtime arguments.PrimitiveActionis the canonical executor input for filesystem, process, git, download, archive, container, and tmux operations.ActionExecutorowns dry-run output, append-only JSONL audit logging, rollback stack management, rollback barriers, and dispatch intoSystemRuntime.
App use-cases construct plans and pass them to the executor for action-backed commands. Direct runtime calls are limited to explicit interactive boundaries such as attaching to tmux or entering a container shell. Domain modules stay free of I/O where the current implementation has pure resolution/planning functions.
Rollback is best-effort and explicit. Actions default to rollbackable; external boundaries such
as shell commands, remote sessions, and non-reversible git/container operations use barrier or
none policies.
Key Design Decision: Modules Are Repos
The _module.yaml files define external git repos that provide content for dotfiles packages.
These module repos are not git submodules -- they are regular git clones managed by flow.
The dotfiles repo itself is also a git clone managed by flow. So all managed git repos (the dotfiles repo + every module repo) share the same abstraction and the same commands.
dotfiles repos is the single entry point for all repo operations. There is no separate
dotfiles modules subcommand group. The --repo=<name> flag filters to a specific repo when
needed (dotfiles repo is named dotfiles, module repos are named by their package, e.g. nvim).
Completed Work
Unified Repos Abstraction
RepoInfo with module_ref is the canonical repo model. _discover_repos() finds the dotfiles
repo and module repos, and repos list/status/pull/push iterate that single collection with an
optional --repo filter. dotfiles init uses the same pull-or-clone flow.
Command Trimming
Removed redundant dotfiles commands:
dotfiles sync: usedotfiles repos pullplusdotfiles linkdotfiles relink:dotfiles linkis idempotentdotfiles undo: usedotfiles unlinkdotfiles clean: broken symlink repair is part of link planningdotfiles modules list/sync: usedotfiles repos list/pull
Feature Completion
dotfiles edit: pull ->$EDITOR/$VISUAL-> scopedgit add-> commit+push, with--no-committo skip auto-commit/push.dotfiles status: module info, link health, and package filtering.dotfiles repos list: all managed repos with name, type, local path, and clone status.--no-color: global flag added tocli.py.--dry-run: supported by dotfiles link/unlink, repos pull/push, packages install, setup run, remote enter, and dev create.
Improvements Over Spec
These are correct deviations -- the implementation improved on the spec:
adapters/containers.py+adapters/tmux.pyextracted as adapters (spec had them inline)core/config_parse.py+core/yaml.pyextracted for config parsingSystemRuntimeextended with containers, tmux, download, and archive runtime fieldsflow.actionsextracted as the canonical execution layer instead of leaving mutation dispatch in individual app use-cases
CI
The GitHub Actions workflow is split into two jobs:
unit: installs dependencies and runspytest tests/ -v --ignore=tests/e2ee2e: verifies Docker is available, setsFLOW_RUN_E2E=1, and runspytest tests/e2e/ -v
Optional Future Work
These are optional refinements, not blockers for the action-centered rewrite.
Global --dry-run
If per-command --dry-run becomes a maintenance burden, promote to a global flag in cli.py.