Skip to content

Latest commit

 

History

History
133 lines (104 loc) · 6.89 KB

File metadata and controls

133 lines (104 loc) · 6.89 KB

Status

The status spec defines how Flow resolves the status of each repo in a workspace. Statuses are evaluated top-to-bottom — the first passing check wins. A workspace's overall status is the least-advanced repo (highest index in the spec).

Location

~/.flow/status.yaml                              # Global default
~/.flow/workspaces/<workspace-id>/status.yaml     # Workspace override (fully replaces global)

Default Statuses

Flow ships with five statuses that model a standard PR-based workflow. These are created automatically on first run at ~/.flow/status.yaml. Run flow reset status to restore defaults after customizing.

Status Color Condition Dependencies
closed dimmed red A merged PR exists for the branch and no open PRs remain gh, jq
stale magenta No commits on the branch in the last 14 days git only
in-review purple A non-draft PR is open for the branch gh, jq
in-progress yellow Uncommitted changes, local commits ahead of remote, or a draft PR git, gh (fallback)
open green Default — none of the above conditions matched none

Check logic details

closed — Requires both conditions: (1) at least one merged PR exists on the branch, AND (2) no open PRs remain. This ensures the workspace isn't marked closed if follow-up PRs are still open.

stale — Compares the timestamp of the most recent commit on the branch against the current time. If the last commit is older than 14 days (1,209,600 seconds), the repo is stale. This is a local-only check that doesn't require GitHub access.

in-review — Checks for any open PR on the branch that is NOT a draft. If you've opened a PR and marked it ready for review, this status matches.

in-progress — Three conditions checked in order (first match wins):

  1. git status --porcelain — uncommitted or unstaged changes in the worktree
  2. git log origin/$BRANCH..HEAD — local commits that haven't been pushed
  3. gh pr list with draft filter — a draft PR exists on the branch

If gh is not installed, checks 1 and 2 still work. The draft PR check gracefully fails (exits non-zero), falling through to the next status.

open — The default fallback. If no check matched, the repo has no detectable work. This typically means the workspace was just created or the branch matches the remote exactly.

Schema

Tip

The check commands are designed to be generated by AI, not written by hand. Describe the condition you want to detect in plain language, then let an agent produce the shell one-liner. Iterate until the check does what you need, then paste it into the spec. The description field is for humans; the check field is for machines.

apiVersion: flow/v1
kind: Status
spec:
  statuses:
    - name: closed
      description: Merged PR, no open PRs remaining
      color: "131"
      check: >-
        gh pr list --repo "$FLOW_REPO_SLUG" --head "$FLOW_REPO_BRANCH" --state merged --json number
        | jq -e 'length > 0' > /dev/null 2>&1
        && gh pr list --repo "$FLOW_REPO_SLUG" --head "$FLOW_REPO_BRANCH" --state open --json number
        | jq -e 'length == 0' > /dev/null 2>&1
    - name: stale
      description: No commits on branch in last 14 days
      color: magenta
      check: >-
        _now=$(date +%s)
        && _last=$(git -C "$FLOW_REPO_PATH" log -1 --format=%ct 2>/dev/null)
        && [ -n "$_last" ]
        && [ $((_now - _last)) -gt 1209600 ]
    - name: in-review
      description: Non-draft open PR on branch
      color: purple
      check: >-
        gh pr list --repo "$FLOW_REPO_SLUG" --head "$FLOW_REPO_BRANCH" --state open --json isDraft
        | jq -e 'map(select(.isDraft == false)) | length > 0' > /dev/null 2>&1
    - name: in-progress
      description: Uncommitted changes, unpushed commits, or draft PR
      color: yellow
      check: >-
        git -C "$FLOW_REPO_PATH" status --porcelain 2>/dev/null | grep -q .
        || git -C "$FLOW_REPO_PATH" log --oneline "origin/$FLOW_REPO_BRANCH..HEAD" 2>/dev/null | grep -q .
        || gh pr list --repo "$FLOW_REPO_SLUG" --head "$FLOW_REPO_BRANCH" --state open --json isDraft
        | jq -e 'map(select(.isDraft)) | length > 0' > /dev/null 2>&1
    - name: open
      description: No changes detected
      color: green
      default: true

Fields

Field Required Description
apiVersion Yes Must be flow/v1
kind Yes Must be Status
spec.statuses[] Yes Must contain at least one entry
spec.statuses[].name Yes Unique status name
spec.statuses[].description No Human-readable description
spec.statuses[].color No Display color — named (green, yellow, purple, magenta, cyan, red, blue, gray) or raw ANSI 256 code (e.g. "131")
spec.statuses[].check Yes* Shell command evaluated via sh -c (*not required for the default entry)
spec.statuses[].default No Exactly one entry must have default: true

Environment Variables

Each check command receives the following environment variables:

Variable Description
FLOW_REPO_URL Repo URL from the state file
FLOW_REPO_BRANCH Branch name from the state file
FLOW_REPO_PATH Absolute path to the worktree directory
FLOW_REPO_SLUG Repo in owner/repo format (derived from URL, works with gh --repo)
FLOW_WORKSPACE_ID Workspace directory ID
FLOW_WORKSPACE_NAME Workspace display name

Resolution

  1. Checks run top-to-bottom per repo. The first check that exits 0 determines that repo's status.
  2. If no check passes, the default status is used.
  3. A workspace's overall status is the least-advanced repo — the one with the highest index in the statuses list.
  4. If a workspace has its own status.yaml, it fully replaces the global spec (no merging).

Display Order

The status table sorts workspaces by status group, then by creation date (most recent first) within each group. The display order is the reverse of the spec order — the default status (bottom of spec) appears at the top of the table, and the most-advanced status (top of spec) appears at the bottom.

Customization

The check commands are shell one-liners. They aren't meant to be human-readable — they're generated by AI agents and only need to exit 0 or non-zero. The description field is what matters for understanding intent; the check field is the machine-evaluated implementation.

You can add, remove, reorder, or rename statuses. The only requirements are:

  • Exactly one entry must have default: true
  • Non-default entries must have a check command
  • Status names must be unique

Checks that depend on gh will gracefully degrade — if gh is not installed, those checks exit non-zero and fall through to the next status. Local-only checks (git, date) work without any external tools.