gh-optivem

command module
v1.6.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: MIT Imports: 37 Imported by: 0

README

gh Commit Stage gh Acceptance Stage gh Release Stage gh Post-Release Stage gh Local Stage

gh-optivem

A GitHub CLI extension for scaffolding pipeline projects.

Prerequisites

GitHub CLI

GitHub CLI is required to install this extension.

Check your version:

gh --version

If the command isn't found or the version is too old, install or upgrade:

  • Install: winget install GitHub.cli (Windows), brew install gh (macOS), or sudo apt install gh / your distro's package manager (Linux)
  • Upgrade: winget upgrade GitHub.cli (Windows), brew upgrade gh (macOS), or sudo apt upgrade gh / your distro's package manager (Linux)
GitHub CLI authentication

You must be logged in to GitHub via the CLI before installing this extension.

Verify you're logged in:

gh auth status

If the command reports you're not logged in, log in:

gh auth login
actionlint

actionlint — used by the Verify scaffolded workflows step.

Check your version:

actionlint -version

If the command isn't found or the version is too old, install or upgrade to the latest v1 release:

go install github.com/rhysd/actionlint/cmd/actionlint@v1

Installation

gh extension install optivem/gh-optivem

Verify the install:

gh optivem --version

Upgrade:

gh extension upgrade optivem

Uninstall:

gh extension remove optivem

Environment Variables

Create these environment variables on your local machine. After setting them, restart your IDE / terminal for the changes to take effect.

These are read from your local environment at scaffold time and then propagated as variables and secrets onto the GitHub repos that gh optivem init creates, so the pipelines it generates can pull base images from Docker Hub under the authenticated rate limit (rather than the much lower anonymous one), publish and pull pipeline images to/from GHCR, send analysis to SonarCloud, and dispatch cross-repo workflows — all without you having to set each secret in the GitHub UI afterwards.

Tokens are read from env vars rather than passed as CLI flags so they don't end up in shell history or ps output, so a single set persists across init, environment show/verify, and re-runs, and so the local input contract matches how GitHub Actions exposes the same secrets to the generated pipelines.

To confirm what your shell is actually exporting (token values masked):

gh optivem environment show

To live-check each token is also accepted by its provider before scaffolding:

gh optivem environment verify

Scaffolding

gh optivem init

Project-stable values — prompted on first run and written to gh-optivem.yaml (or passed as flags for non-interactive runs):

  • --owner — GitHub owner (user or org) for the scaffolded repo(s).
  • --repo — repo name (or monorepo root name for multi-repo layouts).
  • --system-name — human-readable system name (e.g. "Page Turner").
  • --arch — system architecture: monolith or multitier.
  • --repo-strategymonorepo or multirepo.
  • Implementation language — which flag applies depends on --arch:
    • --monolith-lang — system language when --arch monolith: java, dotnet, or typescript.
    • --backend-lang — backend language when --arch multitier: java, dotnet, or typescript.
    • --frontend-lang — frontend language when --arch multitier (currently only typescript).
  • --test-lang — system-test language: java, dotnet, or typescript. Independent of the system language(s).
  • --project-url — URL of the GitHub Project board to attach.
Where gh-optivem.yaml lands
  • Default path (no --config, no $GH_OPTIVEM_CONFIG): gh optivem init writes gh-optivem.yaml only inside the scaffolded repo on GitHub. Nothing is materialized in the current working directory.
  • Explicit path (--config /some/path.yaml or $GH_OPTIVEM_CONFIG=/some/path.yaml): init writes/updates the YAML at the path you named, and the scaffolded repo still gets its own copy (rendered with the auto-created Project URL).
  • Pre-existing <CWD>/gh-optivem.yaml: respected as operator-authored input. Loaded and used as-is; the scaffolded repo still gets its own rendered copy.

Usage

gh optivem provides runner subcommands to build the system, run the system, and run the tests.

System
Compile system

Source-level compile of the system tier (dotnet build / ./gradlew compileJava / npx tsc --noEmit), dispatched per-tier by the lang: field in gh-optivem.yaml.

gh optivem system compile                 # system tier only
gh optivem compile                        # shortcut: system + test tiers (halts on first failure)

compile is the source-level build — distinct from system build (docker compose build / container image build). The two must not be conflated.

Build system

docker compose build for every entry in systems.yaml.

gh optivem system build
gh optivem system build --rebuild         # force full rebuild (no layer cache reuse)
Start system

docker compose up + wait for health.

gh optivem system start
gh optivem system start --restart         # force tear-down + restart
gh optivem system start --log-lines 200   # lines of compose logs to dump on health-probe failure (default 50)
gh optivem system start --up-timeout 10m  # per-attempt timeout for `docker compose up -d` (default 5m)
Stop system

docker compose down + container cleanup.

gh optivem system stop
Clean system

docker compose down -v --rmi local — delete volumes + locally-built images. Analog of dotnet clean / ./gradlew clean: deletes build outputs without touching the dependency cache (registry-pulled images are kept). Chain it explicitly for a fresh start: gh optivem system clean && gh optivem test run.

gh optivem system clean
System tests
Setup tests

Run setupCommands from tests.yaml (npm ci, restore, compile test sources, ...).

gh optivem test setup
Compile tests

Source-level compile of the test tier only.

gh optivem test compile
Run tests

[!WARNING] The system must already be running (gh optivem system start). test run health-probes every entry in systems.yaml first; if any aren't up, it errors out with "start it first with gh optivem system start" rather than silently starting them.

Run all tests:

gh optivem test run                       # run every suite against the already-running system

Run specific suites:

gh optivem test run --suite smoke         # run only the suite with this id
gh optivem test run --suite acceptance-api --suite acceptance-ui   # multiple suites, repeatable
gh optivem test run --suite acceptance-api,acceptance-ui           # ...or comma-separated
gh optivem test run --list                # print suite ids from tests.yaml and exit

Run specific tests:

gh optivem test run --test "MyTest"       # narrow execution to one test name (substituted into the suite's testFilter)
gh optivem test run --test T1 --test T2   # multiple names, repeatable
gh optivem test run --test T1,T2          # ...or comma-separated
gh optivem test run --sample              # use each suite's sampleTest field as the test name

Multi-test semantics depend on the suite's testFilter in tests.yaml. The runner combines multiple --test values per testFilterJoin: "or" (default) joins names with | and substitutes once — works for dotnet (&DisplayName~T1|T2) and playwright/jest (--grep 'T1|T2'); "repeat" substitutes the whole testFilter once per name and concatenates — required for gradle (--tests T1 --tests T2). Practical ceiling on Windows is ~600 typical test names per invocation (the OS caps each command line at 32K characters).

Workspace operations

gh optivem workspace <verb> iterates every repo declared in the resolved *.code-workspace file. It locates the workspace via, in order: the --workspace <dir> flag, the $GH_OPTIVEM_WORKSPACE env var, or by walking up from the current directory.

gh optivem workspace commit "Update settings"             # stage, commit, pull, push every dirty repo
gh optivem workspace commit --repo myrepo "Fix bug"       # only operate on the named repo
gh optivem workspace commit --yes "Sync .claude"          # skip the y/N confirmation (required without a TTY)
gh optivem workspace sync                                 # pull + push every repo (no commit)
gh optivem workspace check-actions                        # latest run of every workflow in every workspace repo
gh optivem workspace rate-limit                           # current GitHub API rate limits and reset times

commit --yes refuses to stage untracked (??) files unless --include-untracked is also passed — the stray-file foot-gun is opt-in for scripted callers.

Cleanup

gh optivem cleanup <verb> bulk-deletes remote artifacts. Each subcommand pre-flights gh api rate_limit before every destructive call and sleeps --delay-seconds (default 10) after each delete to stay under GitHub's 80-mutating-calls/minute secondary limit. Always pass --dry-run first to preview.

gh optivem cleanup releases optivem/greeter-java --dry-run
gh optivem cleanup releases optivem/greeter-java optivem/greeter-dotnet
gh optivem cleanup packages myorg/myrepo --before-date 2026-01-01
gh optivem cleanup repos valentinajemuovic --prefix course-tester- --dry-run
gh optivem cleanup sonar-projects myorg --prefix myorg_course-tester- --dry-run

cleanup releases and cleanup packages take one or more positional owner/repo slugs; cleanup repos and cleanup sonar-projects take a single positional <owner> (or <organization>) followed by either --prefix <prefix>, explicit names/keys, or both. cleanup sonar-projects requires $SONAR_TOKEN (the same token the scaffolder reads).

Further reading

  • Trunk Based Development (TBD) — how to work with main in this repo (and the repos it scaffolds), the role of pull --rebase, when to use short-lived PRs, and why the version-bump bot is just another committer.
  • Process diagram — committed Mermaid diagram of the scaffolding pipeline.

Documentation

Overview

asset_commands.go wires the `gh optivem asset <verb>` subtree. Asset commands manage the embedded global asset tree (methodology docs and Claude Code subagents) that gh-optivem syncs to per-user paths (~/.gh-optivem/docs/, ~/.claude/). Auto-sync runs at startup on every invocation; this subtree exists for the explicit-force form needed when the auto-sync escape hatch is set.

cleanup_commands.go wires the `gh optivem cleanup <verb>` subtree. The cleanup noun spans bulk-destructive operations against remote systems (GitHub releases/packages/repos, SonarCloud projects). The Go ports replace the bash scripts in academy/github-utils/scripts/ — see plans/20260514-0914-migrate-workspace-scripts-to-gh-optivem.md.

The DRY_RUN env var idiom from bash becomes a `--dry-run` flag here (consistent with the rest of gh-optivem). Each subcommand pre-flights `gh api rate_limit` before each destructive call via internal/shell.

compile_commands.go wires the bare `gh optivem compile` verb and the tier-level helpers (compileSystem, compileSystemTests, monolithTier, loadProjectConfigOrExit) shared with the noun-scoped forms (`gh optivem system compile` in system_commands.go and `gh optivem test compile` in test_commands.go).

Naming: `compile` is source-level build (dotnet build / gradlew compileJava / npx tsc). `build` is reserved for `docker compose build` (system_commands.go, under the `system` noun). The two are distinct enough to coexist; they must not be conflated.

`compile` stays a bare verb (no parent noun) because it spans tiers — the bare form runs `system compile` then `test compile` in sequence, halting on first failure. This shortcut is the dominant use case (the structural-cycle compile_all action shells out to it as a single command). Same category as `gh browse` / `gh status` in gh's own surface: cross-resource, no single noun to slot under. The noun-scoped forms stay available for scoped local use.

compile_summary.go collects per-tier outcomes during a `gh optivem compile` run and prints a compact tail summary, so the user can scan success/failure without scrolling the (often long) compile output.

One row per `compiler.Compile` call (i.e. per tier). Per-command timing inside the compiler package is deliberately not threaded through — the compile_commands.go level is the right granularity, and keeping the `compiler` package's `error`-only API intact preserves its testable seam.

config_commands.go wires the `gh optivem config …` subcommands into the root Cobra command. The `config` namespace owns operations that read or write gh-optivem.yaml — the central per-project config file produced by `gh optivem init` and consumed by `gh optivem implement`.

gh optivem config init      — write a fresh gh-optivem.yaml from CLI flags
gh optivem config validate  — parse <CWD>/gh-optivem.yaml and validate it
gh optivem config preflight — validate + check on-disk layout exists

`config init` reuses the same render path as `gh optivem init` (steps.WriteOptivemYAMLToPath / config.ValidateAndDeriveForYAML) so a new YAML-affecting flag flows to both surfaces with no per-command duplication.

doctor_commands.go wires the `gh optivem doctor` command. It verifies the three global git config keys docs/tbd.md requires for trunk-based development. With --fix, it sets any missing or wrong values at the global level. Replaces the "copy these three commands out of the doc" onboarding step with one command.

Scope is intentionally narrow — config only. Broader repo-health checks belong in their own command, not here.

environment_commands.go wires the `gh optivem environment` subtree. The `environment` noun owns read-only operations on the local shell environment the gh-optivem CLI reads from — credentials and other inputs alike (e.g. DOCKERHUB_USERNAME is an account name, not a token, but is still required from the environment).

gh optivem environment show   — print each env var, with token values
                                 masked, so you can confirm what your
                                 shell is exporting without leaking the
                                 secret to terminal scrollback.
gh optivem environment verify — check every credential and required
                                 local tool (gh CLI auth, actionlint),
                                 returning non-zero on any missing or
                                 rejected value.

`verify` is designed to be invoked from a CI preflight job so a single broken input surfaces once, before a scaffolding matrix fans out and burns runner minutes failing the same way N times. `show` is the local counterpart — judgment-free output for humans debugging their setup.

implement_commands.go wires the `gh optivem implement` subcommand into the root Cobra command. The single `implement` verb absorbs what used to be two commands (`atdd implement-ticket` and `atdd manage-project`): one entry point, branching on whether `--issue` is set.

gh optivem implement                # pick the top Ready item
gh optivem implement --issue 42     # walk the pipeline for a specific issue

The handler is deliberately thin: it translates Cobra flags into internal/atdd/runtime/* calls and surfaces their errors via exitOnError (defined in runner_helpers.go) for consistency with the rest of the `optivem` binary.

Why "implement" as a top-level verb (not under a methodology noun): the pipeline orchestrated here is the stable concept; *which* methodology runs (ATDD today, TDD/DDD or compositions later) is configuration read from `gh-optivem.yaml` (process_flow:, agent_prompts:, node_extras:, node_replacements:). Hoisting `implement` to the root keeps the muscle memory ("implement an issue") even when a second methodology lands.

gh-optivem: A gh CLI extension for pipeline project management.

Usage:

Monolith:
  gh optivem init --owner acme --system-name "Page Turner" --repo page-turner \
      --arch monolith --monolith-lang java

Multitier:
  gh optivem init --owner acme --system-name "Page Turner" --repo page-turner \
      --arch multitier --backend-lang java --frontend-lang typescript

preflight_helpers.go builds the wired-up preflight.Options the cobra layer passes to preflight.Run. Both `gh optivem implement` and `gh optivem config preflight` go through this helper so the two surfaces share one definition of "what real remote checks does preflight run" — adding or removing a remote check class touches one place, not two.

Token requirements:

  • GitHub: relies on whatever auth `gh` CLI is already configured with (`gh auth login` or $GH_TOKEN / $GITHUB_TOKEN). No extra plumbing.
  • SonarCloud: requires $SONAR_TOKEN whenever cfg.Sonar.Organization is set. Missing token is a hard error so preflight never silently skips a check class the operator's config implies should run.

process_commands.go wires the `gh optivem process` parent and its children. The intent is the "view, don't generate" principle: consumers and CI alike can read the same artifact gh-optivem produces, with no per-repo tooling.

gh optivem process show           # render the Mermaid process-flow diagram
gh optivem process show > docs/process-diagram.md

`process` is a noun group, not a methodology namespace. The artifact described (the configured process flow) belongs to *the process*, not to *the methodology* — keeping it grouped under `process` ages better when TDD/DDD or compositions land, and matches the existing noun-first surface (`system`, `test`, `config`, `environment`).

runner_helpers.go holds the cross-cutting helpers used by the runner-tier commands. The command wiring itself lives in `system_commands.go` and `test_commands.go` — split per the noun-first surface (`gh optivem system <verb>` / `gh optivem test <verb>`). The runner package is fully agnostic — these helpers translate Cobra flags into runner.* calls and resolve config paths against gh-optivem.yaml.

Working-dir contract: each command operates against the user's current working directory. A gh-optivem.yaml is required; its system.config: / system_test.config: fields drive path resolution. An alternate gh-optivem.yaml can be selected via --config / -c.

system_commands.go wires the `gh optivem system <verb>` subtree. The system noun spans the lifecycle verbs that operate on the scaffolded project's running containers (build, start, stop, clean) plus the source-level system tier compile.

Working-dir contract: every command runs against the user's cwd and reads the systems config path from gh-optivem.yaml's system.config: field (legacy `.json` files still resolve via the loader's extension dispatch). An alternate gh-optivem.yaml can be selected via --config / -c. Missing gh-optivem.yaml or empty system.config: are hard errors. Helpers live in runner_helpers.go.

test_commands.go wires the `gh optivem test <verb>` subtree. The test noun owns the test-tier lifecycle verbs: `run` against an already-running system, `setup` for harness preparation, and `compile` for the test-tier source build.

Working-dir contract: every command runs against the user's cwd and reads the tests config path from gh-optivem.yaml's system_test.config: field (legacy `.json` files still resolve via the loader's extension dispatch). An alternate gh-optivem.yaml can be selected via --config / -c. Missing gh-optivem.yaml or empty system_test.config: are hard errors. Helpers live in runner_helpers.go.

workspace_commands.go wires the `gh optivem workspace <verb>` subtree. The workspace noun spans operations that iterate every repo declared in the resolved *.code-workspace file. The Go ports replace the bash scripts in github-utils/scripts/ — see plans/20260514-0914-migrate-workspace- scripts-to-gh-optivem.md.

Cascade for locating the workspace: --workspace > $GH_OPTIVEM_WORKSPACE > walk up from CWD. Resolution lives in internal/workspace.

Directories

Path Synopsis
internal
assets
Package assets exposes the single embedded asset tree for gh-optivem.
Package assets exposes the single embedded asset tree for gh-optivem.
assets/sync
Package sync writes the embedded global/ asset tree to per-user paths so methodology docs and Claude Code subagents are reachable on the user's filesystem without per-repo install ceremony.
Package sync writes the embedded global/ asset tree to per-user paths so methodology docs and Claude Code subagents are reachable on the user's filesystem without per-repo install ceremony.
atdd/runtime/actions
Bindings — Go implementations of every service-task `action:` referenced in docs/atdd/process/process-flow.yaml.
Bindings — Go implementations of every service-task `action:` referenced in docs/atdd/process/process-flow.yaml.
atdd/runtime/agents
Package agents holds the user-task agent-dispatch registry.
Package agents holds the user-task agent-dispatch registry.
atdd/runtime/board
Package board owns the GitHub Project board interactions for the ATDD pipeline driver.
Package board owns the GitHub Project board interactions for the ATDD pipeline driver.
atdd/runtime/classify
Package classify is the fast-path ticket classifier for the ATDD pipeline driver.
Package classify is the fast-path ticket classifier for the ATDD pipeline driver.
atdd/runtime/clauderun
Package clauderun shells out to the `claude` CLI to dispatch a named ATDD agent for the current phase, replacing v1's "pause and let the operator launch the agent in a second window" workflow.
Package clauderun shells out to the `claude` CLI to dispatch a named ATDD agent for the current phase, replacing v1's "pause and let the operator launch the agent in a second window" workflow.
atdd/runtime/diagram
Package diagram renders the canonical Mermaid markdown for the ATDD process flow.
Package diagram renders the canonical Mermaid markdown for the ATDD process flow.
atdd/runtime/driver
Package driver wires together the ATDD pipeline runtime: it loads the process-flow YAML, registers gates / actions / agents, applies override and verify decorators, and walks the named process end to end.
Package driver wires together the ATDD pipeline runtime: it loads the process-flow YAML, registers gates / actions / agents, applies override and verify decorators, and walks the named process end to end.
atdd/runtime/gates
Bindings — Go implementations of every gateway `binding:` referenced in docs/atdd/process/process-flow.yaml.
Bindings — Go implementations of every gateway `binding:` referenced in docs/atdd/process/process-flow.yaml.
atdd/runtime/intake
Package intake holds the deterministic markdown parser that replaces the four LLM-driven intake agents (atdd-story / atdd-bug / atdd-task / atdd-chore).
Package intake holds the deterministic markdown parser that replaces the four LLM-driven intake agents (atdd-story / atdd-bug / atdd-task / atdd-chore).
atdd/runtime/override
Package override implements the per-step override-hook decorator.
Package override implements the per-step override-hook decorator.
atdd/runtime/preflight
Package preflight validates that the consumer's gh-optivem.yaml maps onto a real on-disk layout and a real remote setup before any ATDD agent or board work runs.
Package preflight validates that the consumer's gh-optivem.yaml maps onto a real on-disk layout and a real remote setup before any ATDD agent or board work runs.
atdd/runtime/release
Package release owns the end-of-cycle release mechanics for the ATDD pipeline driver: regex-remove `@Disabled`-style markers from in-scope test files, commit, and close the GitHub issue.
Package release owns the end-of-cycle release mechanics for the ATDD pipeline driver: regex-remove `@Disabled`-style markers from in-scope test files, commit, and close the GitHub issue.
atdd/runtime/repolocator
Package repolocator turns a parsed projectconfig.Config into a map from repo slug → absolute local clone path.
Package repolocator turns a parsed projectconfig.Config into a map from repo slug → absolute local clone path.
atdd/runtime/statemachine
Embed binds the canonical process-flow document into the statemachine package binary.
Embed binds the canonical process-flow document into the statemachine package binary.
atdd/runtime/testselect
Package testselect computes the minimal-but-safe set of acceptance and contract tests to run after a driver-adapter change.
Package testselect computes the minimal-but-safe set of acceptance and contract tests to run after a driver-adapter change.
atdd/runtime/trace
Package trace adds a per-node logging decorator to the engine, producing a chronological audit trail of every step the ATDD pipeline takes:
Package trace adds a per-node logging decorator to the engine, producing a chronological audit trail of every step the ATDD pipeline takes:
atdd/runtime/tracker
Package tracker is the seam between the ATDD pipeline driver and the concrete issue-tracker backend (GitHub Projects today, markdown files for the local/offline path, Jira tomorrow).
Package tracker is the seam between the ATDD pipeline driver and the concrete issue-tracker backend (GitHub Projects today, markdown files for the local/offline path, Jira tomorrow).
atdd/runtime/tracker/github
Package github implements tracker.Tracker against GitHub Projects v2.
Package github implements tracker.Tracker against GitHub Projects v2.
atdd/runtime/verify
Bindings — per-node pre/post-condition checks.
Bindings — per-node pre/post-condition checks.
compiler
Package compiler runs source-level compile sequences for one tier of a scaffolded project, dispatching by language.
Package compiler runs source-level compile sequences for one tier of a scaffolded project, dispatching by language.
config
Package config provides CLI parsing, validation, and the Config struct.
Package config provides CLI parsing, validation, and the Config struct.
configinit
Package configinit owns the shared "produce a gh-optivem.yaml" code path.
Package configinit owns the shared "produce a gh-optivem.yaml" code path.
files
Package files provides file manipulation helpers: replace, rename, walk.
Package files provides file manipulation helpers: replace, rename, walk.
ghbulk
Package ghbulk ports the paginated bulk-delete helpers from github-utils/scripts/{delete-releases,delete-packages,delete-repos}.sh.
Package ghbulk ports the paginated bulk-delete helpers from github-utils/scripts/{delete-releases,delete-packages,delete-repos}.sh.
log
Package log provides colored logging helpers.
Package log provides colored logging helpers.
pathx
Package pathx contains small cross-platform path helpers shared across packages that exec subprocesses.
Package pathx contains small cross-platform path helpers shared across packages that exec subprocesses.
projectconfig
Package projectconfig loads the consumer repo's per-project configuration file at gh-optivem.yaml (project root).
Package projectconfig loads the consumer repo's per-project configuration file at gh-optivem.yaml (project root).
promptio
Package promptio centralises every human y/n decision the CLI surfaces.
Package promptio centralises every human y/n decision the CLI surfaces.
runner
Package runner orchestrates docker-compose-backed system tests using two YAML config files (with legacy JSON fallback): a systems.yaml (compose + health probes) and a tests.yaml (setup commands + suites).
Package runner orchestrates docker-compose-backed system tests using two YAML config files (with legacy JSON fallback): a systems.yaml (compose + health probes) and a tests.yaml (setup commands + suites).
shell
Package shell provides GitHub CLI wrapper and subprocess helpers.
Package shell provides GitHub CLI wrapper and subprocess helpers.
sonar
Package sonar wraps the SonarCloud REST endpoints the cleanup command uses (api/projects/search, api/projects/delete).
Package sonar wraps the SonarCloud REST endpoints the cleanup command uses (api/projects/search, api/projects/delete).
spinner
Package spinner shows an animated liveness indicator for long-running waits where the duration is unknown.
Package spinner shows an animated liveness indicator for long-running waits where the duration is unknown.
steps
Package steps implements the scaffold pipeline steps.
Package steps implements the scaffold pipeline steps.
templates
Package templates provides template helpers: copy workflows, fixups.
Package templates provides template helpers: copy workflows, fixups.
version
Package version provides build-time version information.
Package version provides build-time version information.
workspace
Package workspace resolves the workspace root and enumerates the repo folders declared in its *.code-workspace file.
Package workspace resolves the workspace root and enumerates the repo folders declared in its *.code-workspace file.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL