forge-orchestrator 1.8.0

Orchestration for Claude Code on shared repos, with Codex CLI and Antigravity CLI (agy) as task runners — single Rust binary, zero deps.
Documentation
#!/usr/bin/env python3
"""The README's CLI text comes from the binary (EMMA-SOUL Dx3 73d06ff8 item 6).

Two checks, both against the forge binary given with --forge:
1. The block between the forge-help markers is the verbatim `forge --help` output (trailing
   whitespace stripped). `--write` regenerates it; without it, any difference fails.
2. Every forge invocation in a bash/sh/console or bare code block names a real command, and every
   flag on it is listed by `forge <command> --help` (or by `forge --help` for global flags). An
   invocation is `forge` at the start of a command: the line start, after `&&`, `||`, `;` or `|`,
   or after a `--` that hands the rest of the line to another program (`codex mcp add forge --
   forge mcp`).

Usage: readme-cli.py --forge target/debug/forge [--readme README.md] [--write]
Exit 1 with one line per mismatch.
"""
import argparse
import os
import re
import subprocess
import sys

START = "<!-- forge-help:start (generated by .github/scripts/readme-cli.py --write; do not edit) -->"
END = "<!-- forge-help:end -->"


def run_help(forge, *args):
    # No colour, whatever the caller's environment says: CLICOLOR_FORCE=1 would put escape codes in.
    env = {k: v for k, v in os.environ.items() if k not in ("CLICOLOR_FORCE", "CLICOLOR")}
    env["NO_COLOR"] = "1"
    out = subprocess.run([forge, *args, "--help"], capture_output=True, text=True, check=True,
                         env=env).stdout
    return "\n".join(line.rstrip() for line in out.splitlines()).strip("\n")


def help_block(forge):
    return f"{START}\n```text\n$ forge --help\n{run_help(forge)}\n```\n{END}"


def commands(top_help):
    """Subcommand names from the Commands: section of `forge --help`."""
    names, inside = set(), False
    for line in top_help.splitlines():
        if line.strip() == "Commands:":
            inside = True
            continue
        if inside:
            m = re.match(r"^  ([a-z][a-z0-9-]*)\s", line + " ")
            if m:
                names.add(m.group(1))
            elif line and not line.startswith(" "):
                inside = False
    return names


def flags(help_text):
    return set(re.findall(r"(?<![\w-])(--[a-z0-9][a-z0-9-]*|-[a-zA-Z])\b", help_text))


def code_lines(readme):
    """Lines inside ```bash / ```sh / ```console fences and bare ``` fences."""
    open_fence, scanned = False, False
    for n, line in enumerate(readme.splitlines(), 1):
        fence = re.match(r"^\s*```(\w*)", line)
        if fence:
            # A fence line opens a block when none is open and closes it otherwise, so a closing
            # bare ``` is never read as the opening of a new bare block.
            open_fence = not open_fence
            scanned = open_fence and fence.group(1) in ("", "bash", "sh", "shell", "console")
            continue
        if scanned:
            yield n, line


def check_commands(readme, forge, top_help):
    errors, cmds, global_flags, cache = [], commands(top_help), flags(top_help), {}
    for n, line in code_lines(readme):
        text = re.sub(r"^\s*\$\s*", "", line.split("#", 1)[0]).strip()
        for words in invocations(text):
            errors += check_invocation(n, words, forge, cmds, global_flags, cache)
    return errors


def invocations(text):
    """The word lists of each forge invocation on one shell line."""
    for segment in re.split(r"\s*(?:&&|\|\||;|\|)\s*", text):
        words = segment.split()
        for i, w in enumerate(words):
            if w == "forge" and (i == 0 or words[i - 1] == "--") and len(words) > i + 1:
                yield words[i:]
                break


def check_invocation(n, words, forge, cmds, global_flags, cache):
    errors = []
    cmd = words[1]
    if cmd.startswith("-"):
        return errors
    if cmd not in cmds:
        errors.append(f"README.md:{n}: `forge {cmd}` is not a forge command (forge --help)")
        return errors
    if cmd not in cache:
        cache[cmd] = flags(run_help(forge, cmd))
    for w in words[2:]:
        flag = w.split("=", 1)[0]
        if re.fullmatch(r"--?[A-Za-z0-9][A-Za-z0-9-]*", flag) and flag not in cache[cmd] | global_flags:
            errors.append(f"README.md:{n}: `forge {cmd} {flag}` is not listed by `forge {cmd} --help`")
    return errors


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--forge", required=True)
    ap.add_argument("--readme", default="README.md")
    ap.add_argument("--write", action="store_true")
    a = ap.parse_args()
    with open(a.readme, encoding="utf-8", newline="") as f:
        readme = f.read()
    pattern = re.compile(re.escape(START) + r".*?" + re.escape(END), re.S)
    found = pattern.findall(readme)
    want = help_block(a.forge)
    errors = []
    if len(found) != 1:
        errors.append(f"{a.readme}: want exactly one forge-help block, found {len(found)}")
    elif a.write:
        readme = pattern.sub(lambda _: want, readme)
        with open(a.readme, "w", encoding="utf-8", newline="") as f:
            f.write(readme)
        print(f"readme-cli: wrote the forge --help block in {a.readme}")
    elif found[0] != want:
        errors.append(f"{a.readme}: the forge-help block differs from `forge --help`; run "
                      ".github/scripts/readme-cli.py --forge <forge> --write")
    errors += check_commands(readme, a.forge, run_help(a.forge))
    for e in errors:
        print(f"::error::{e}")
    print(f"readme-cli: {'FAIL' if errors else 'ok'} ({len(errors)} problem(s))")
    return 1 if errors else 0


if __name__ == "__main__":
    sys.exit(main())