Flow is a minimal Droid plugin for lightweight feature-based delivery sessions.
It keeps canonical state in .flow/sessions/<id>/session.json, renders session docs under .flow/sessions/<id>/docs/ for humans, and routes planning, execution, status, and reset through one Python runtime.
- Commands:
/flow-plan,/flow-run,/flow-status,/flow-reset - Canonical state:
.flow/sessions/<id>/session.json - Rendered docs:
.flow/sessions/<id>/docs/index.md,.flow/sessions/<id>/docs/features/*.md,.flow/sessions/<id>/docs/decisions/*.md, and.flow/sessions/<id>/reviews/*.md - Runtime entrypoint:
scripts/flow_runtime.py - Commands, droids, and hooks do not write
.flow/state directly
droid plugin marketplace add https://github.com/ddv1982/flow-droid
droid plugin install flow@flow-droiddroid plugin marketplace add /path/to/flow-droid
droid plugin install flow@flow-droiddroid plugin update flow@flow-droid/flow-plan <goal>
/flow-plan # review the draft features and approve the plan
/flow-run
/flow-status
/flow-plancreates or reshapes the active session./flow-plancan run bounded Exa/Ref-backed research when the user choosesResearch and plan, then records a defensible implementation approach before approval.- When
/flow-planis showing a draft review, the immediate follow-up is choosing one of the runtime-provided review actions. Typed replies likeapproveandapprove <ids>remain fallback aliases. apply-planis the transactional commit point for a replacement plan./flow-runexecutes one active feature at a time, requires strict structured worker results, and does not complete a feature unless validation and required review gates pass./flow-statusreflects runtime-provided action guidance likerecommendedActionandavailableActions, not hand-reconstructed next steps./flow-resetreopens one feature or archives the active session.- The normal path is
plan -> review -> approve -> run; feature trimming and research skipping are optional advanced choices.
| Command | Purpose |
|---|---|
/flow-plan |
Create or refresh the active draft session |
/flow-run |
Run or continue the active feature |
/flow-status |
Show the active session or list sessions |
/flow-reset |
Reopen a feature or archive the active session |
The stable runtime entrypoint is scripts/flow_runtime.py.
The startup hook calls the installed plugin runtime directly.
The runtime is responsible for:
- creating or reusing sessions
- validating session payloads
- persisting
session.jsonatomically - rendering session docs
- selecting the next runnable feature
- applying planner and worker result payloads
- resetting or archiving sessions
- rendering startup and status summaries
Runtime CLI subcommands:
plan-startplan-requestapply-planselect-featuresapprove-planstart-runcomplete-featureblock-runblockresetstatusstatus-summaryworkspace-fingerprintvalidate
.flow/
├── active
├── .gitignore
├── archive/
└── sessions/
└── <session-id>/
├── session.json
├── docs/
│ ├── index.md
│ └── features/
│ └── <feature-id>.md
│ └── decisions/
│ └── adr-001-<slug>.md
└── reviews/
└── <feature-id>-review.md
session.json stores:
versionidgoalstatusapprovalplanningplanexecutionnotesartifactstimestamps
plan stores:
summaryoverviewrequirementsarchitectureDecisionsas an ordered array of decision text stringsfeatures
Each feature stores:
idtitlesummarystatusfileTargetsverification- optional
dependsOncontaining feature ids from the same plan - optional
blockedBycontaining feature ids from the same plan; not free-text blocker notes - optional
relatedDecisionIdsusing canonical ids likeadr-001; planner payloads may instead providerelatedDecisionstext and let the runtime resolve canonical ids - optional
result
Feature results store:
summaryartifactsChangedvalidationRundecisionsnotesverificationStatusfollowUpsfeatureReviewSummary- optional
finalReviewSummary completedAt
Execution state also keeps a canonical currentFocus record so session overviews and status output can explain the next recommended feature and why it should be tackled next.
execution stores:
activeFeatureIdblockedReasonblockedAtlastExecutionSummary
planning stores:
intentlastPlanSummary
Flow uses two droids:
flow-planner: returns a compact feature plan payloadflow-worker: completes one active feature and returns a worker result payload
The runtime owns state transitions and validates returned payloads.
Planner payloads use a lighter validation contract:
validationRun: array of strings only- planner runs are read-only, so
validationRunshould usually be[]
Worker result payloads are intentionally strict:
artifactsChanged: array of{ "path", optional "kind" }validationRun: array of{ "command", "status", "summary" }wherestatusis one ofpassed,failed,failed_existing, orpartialdecisions: array of{ "summary" }featureResult.featureId: required and must match the active feature idfeatureReview: required for every featurefinalReview: required only for the final remaining feature
Flow does not complete a feature unless validation passes and the required review payloads report passed.
The session-start hook resolves the installed plugin runtime and calls status-summary so startup messaging stays aligned with /flow-status.
If startup status fails, the hook surfaces a concise error to stderr.
Important files:
pyproject.tomlflow_runtime_lib/scripts/flow_runtime.pyscripts/run_flow_runtime.shscripts/flow_plan_fallback.pyflow_runtime_lib/cli.pyflow_runtime_lib/store.pyflow_runtime_lib/schema/flow_runtime_lib/render.pyflow_runtime_lib/engine/commands/flow-plan.mdcommands/flow-run.mdcommands/flow-status.mdcommands/flow-reset.mddroids/flow-planner.mddroids/flow-worker.mdskills/using-flow/SKILL.md
python3 -c "import flow_runtime_lib; import flow_runtime_lib.schema.evidence"
python3 -m unittest tests.test_flow_command_contracts
bash tests/validate-plugin.sh
python3 tests/workflow-fixtures.py
python3 tests/command-order-scenarios.py
python3 tests/smoke-flow-session.pyPython packaging notes:
flow_runtime_libis the importable runtime package name.pyproject.tomldeclaresflow_runtime_lib/as the packaged source tree for tooling and installs.scripts/*.pyentrypoints prepend the repo root so direct script execution resolves the package consistently.
- Runtime logic is authoritative.
session.jsonis canonical.- rendered session docs are derived.
- Commands and hooks delegate to the runtime.
- Droids return payloads and do not write session state directly.
- Plans are compact and feature-based.
- The runtime accepts worker results only for the active feature.