# 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 # Host only. SSH+tmux into VM. flow remote list # List configured targets. flow dev create -i # VM only. Create+start container. flow dev attach # Attach to container tmux session. flow dev exec [cmd...] # Run command in container. flow dev enter # Interactive shell in container. flow dev list # List dev containers. flow dev stop # Stop container. flow dev rm # Remove container. flow dev respawn # Respawn tmux panes. flow dotfiles init --repo # 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 # 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 # Show profile plan. flow packages install [name...] [--profile p] [--dry-run] flow packages list [--all] # List packages. flow packages remove [--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` -> `dot` - `packages` -> `package`, `pkg` - `projects` -> `project`; `flow sync` -> `flow projects check --fetch` - `setup` -> `bootstrap`, `provision` - `remote enter` -> `enter` - `dev attach` -> `dev connect` - `dev rm` -> `dev remove` - `dotfiles 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`. - `ActionPlan` is the unit of execution. It can contain high-level `DomainAction` entries and direct `PrimitiveAction` entries. - `DomainAction` records 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. - `PrimitiveAction` is the canonical executor input for filesystem, process, git, download, archive, container, and tmux operations. - `ActionExecutor` owns dry-run output, append-only JSONL audit logging, rollback stack management, rollback barriers, and dispatch into `SystemRuntime`. 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=` 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`: use `dotfiles repos pull` plus `dotfiles link` - `dotfiles relink`: `dotfiles link` is idempotent - `dotfiles undo`: use `dotfiles unlink` - `dotfiles clean`: broken symlink repair is part of link planning - `dotfiles modules list/sync`: use `dotfiles repos list/pull` ### Feature Completion - `dotfiles edit`: pull -> `$EDITOR`/`$VISUAL` -> scoped `git add` -> commit+push, with `--no-commit` to 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 to `cli.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.py` extracted as adapters (spec had them inline) - `core/config_parse.py` + `core/yaml.py` extracted for config parsing - `SystemRuntime` extended with containers, tmux, download, and archive runtime fields - `flow.actions` extracted 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 runs `pytest tests/ -v --ignore=tests/e2e` - `e2e`: verifies Docker is available, sets `FLOW_RUN_E2E=1`, and runs `pytest 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`.