OrcAI.Tool 0.8.0

There is a newer version of this package available.
See the version list below for details.
dotnet tool install --global OrcAI.Tool --version 0.8.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local OrcAI.Tool --version 0.8.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=OrcAI.Tool&version=0.8.0
                    
nuke :add-package OrcAI.Tool --version 0.8.0
                    

OrcAI CLI

<p align="center"> <img src="assets/orcai_banner.png" alt="OrcAI" /> </p>

A CLI tool for orchestrating bulk GitHub work across many repositories. From a single YAML config, OrcAI creates a GitHub Project, opens templated issues in every target repo, and hands them off to whoever (or whatever) does the work — a human teammate, a bot, or an AI agent like GitHub Copilot or OpenCode.

Features

  • Declarative YAML jobs — one config defines the project, target repos, issue template, assignment behaviour, nudge policy, and notification template.
  • Bulk, idempotent issue creation across any number of repos — a lock file makes re-runs free; glob and brace expansion ("jobs/**/*.{yml,yaml}") for fanning out.
  • GitHub Project auto-management — finds or creates the board and links every issue to it.
  • Assign to anyone — assign.to accepts any GitHub user, bot, or GitHub App handle. Default is @copilot, but humans, OpenCode, and custom App bots all work.
  • Comment-based triggers — assign.via: comment posts a slash command (e.g. /opencode) instead of assigning, for agents that listen for mentions. comment-and-assign does both.
  • Tag anyone in templated comments — assign.comment, nudge.comment, and notify all support {assignee}, {job.owner}, and {repo.codeowners} tokens, resolved from YAML and CODEOWNERS files at runtime.
  • orcai nudge — re-trigger stale issues (no linked PR yet) by reassignment, comment, or both.
  • orcai notify — broadcast a templated comment to issues and/or PRs from the lock file; filter by state, dry-run, and inject extra --data key=value template variables.
  • Auto issue-body updates — when the Markdown template changes, existing issues' bodies are updated without re-running the structural work (hash-based detection).
  • Robust at scale — built-in rate limiting (60 writes/min, configurable) with exponential-backoff retry; closed-issue policy (create/reopen/skip/fail); concurrency control; --continue-on-error; JSON output for CI.
  • Multiple auth methods — ambient gh CLI, PAT, or GitHub App (manifest flow supported via orcai auth create-app). A PAT is only required when the assignee is @copilot.

Installation

OrcAI is distributed as a .NET global tool. Requires .NET 10 or later.

dotnet tool install --global OrcAI.Tool

Then run it as orcai.

Prerequisites

  • gh CLI: Install from cli.github.com — must be installed and on PATH
  • Authentication: The easiest option is to ensure gh is authenticated (gh auth login). OrcAI will use it automatically. For other methods see docs/cli-reference.md.

Quick start

1. Authenticate

The simplest option — if you already use the gh CLI, just make sure it's authenticated:

gh auth login

That's it. OrcAI will pick up the token automatically.

For PAT, GitHub App, or environment variable auth see docs/cli-reference.md.

2. Run a job

# Single config file
orcai run jobs/my-upgrade.yml

# All configs in a directory (quote the glob to prevent shell expansion)
orcai run "jobs/*.yml" --continue-on-error --json

# Limit concurrency to avoid rate limits
orcai run "jobs/*.yml" --max-concurrency 2

run finds or creates a GitHub Project, creates issues from your template, adds them to the project, and triggers the configured assignee — whether that's @copilot, another bot, an AI agent like OpenCode, or a human teammate. Triggering can be via assignment, a templated comment (e.g. a slash command), or both. On success a lock file (<basename>.lock.json) is written alongside the YAML for fast idempotent re-runs.

Commands

Command Description
orcai auth pat/app/create-app/switch Store credentials or switch profiles for all other commands
orcai generate Scaffold a YAML job config and stub issue template
orcai run Execute a bulk upgrade job (supports globs, concurrency control, JSON output)
orcai nudge Re-trigger stale issues with no linked PR (reassign, comment, or both)
orcai notify Post a templated comment to issues and/or PRs from the lock file
orcai validate Validate YAML config(s) and verify all repos are accessible
orcai info Display the current state of a job
orcai cleanup Tear down everything created by run

For full flag details, output formats, lock file schema, and advanced usage see docs/cli-reference.md. For config file settings see docs/config.md.

The original Nushell scripts (orca.nu, cleanup.nu) are documented in docs/nushell-scripts.md.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.10.6 116 10/6/2026
0.10.5 216 9/7/2026
0.10.4 145 9/3/2026
0.10.3 128 9/2/2026
0.10.2 116 9/2/2026
0.10.1 122 9/1/2026
0.10.0 134 8/30/2026
0.9.0 126 8/30/2026
0.8.1 313 6/16/2026
0.8.0 190 6/9/2026
0.7.5-beta6 130 6/9/2026
0.7.4-beta5 124 5/21/2026
0.7.3-beta4 140 5/19/2026
0.7.2-beta3 135 5/18/2026
0.7.1-beta2 146 5/18/2026
0.7.0-beta1 134 5/13/2026
0.6.0 189 5/7/2026
0.5.1 320 3/17/2026
0.5.0 192 3/16/2026
0.4.4 194 3/16/2026
Loading failed

`orcai run --dryrun` — preview what would be created, reopened, or updated without making any GitHub API calls or writing the lock file. Read-only lookups still run so the preview reflects current state. Outcomes are reported per repo as `would create`, `would reopen`, or `would update`, with a summary line and `dryRunWouldCreate` / `dryRunWouldReopen` / `dryRunWouldUpdate` counts in `--json`.
`orcai notify` command — posts a templated comment to issues and/or PRs recorded in the lock file. Supports the same `{assignee}`, `{job.owner}`, and `{repo.codeowners}` template tokens as `nudge.comment`.
`--target issues|prs|both` — which lock file items to notify (default: `issues`).
`--state open|closed|all` — filter by current GitHub state before commenting (default: `open`); `closed` matches both closed and merged PRs; `all` skips the live state check entirely.
`--dryrun` — preview which items would be notified without posting any comments.
`--verbose` — print per-item progress to stderr.
`--template <string>` — inline comment template supplied directly on the CLI; overrides `notify.comment` from YAML/config.
`--data key=value` — inject an extra template variable (repeatable). E.g. `--data sprint=42`.
`--json-data <json>` — inject extra template variables as a JSON object string. Merged with `--data`; `--data` takes precedence on key conflicts. User-supplied values override built-in tokens (`{assignee}` etc.) when the same key is used.
`notify` block in YAML job config and global/local JSON config — configures the comment template for `orcai notify`.
`notify.comment` — comment body template. Supports the same `{assignee}`, `{job.owner}`, and `{repo.codeowners}` tokens as `nudge.comment`.
`orcai run` records repos that were skipped because they are archived in a new `skippedRepos` field in the lock file. The run summary and `--json` output include a `skippedArchived` count and status.
`orcai run` detects when the lock file points to a deleted or transferred issue and recreates the issue in place instead of failing. New `staleIssueRecreated` count/status in the summary and `--json` output; the lock file is rewritten with the new issue numbers.
`orcai run` now persists error information in the lock file when a repo fails to process, allowing errors to be surfaced in subsequent runs instead of being silently ignored as "not created". New `failures` field in the lock file maps repo, attempts, and action that failed.
`orcai nudge` and `orcai notify` rename `--dry-run` to `--dryrun` for consistency with `cleanup` (and the new `run --dryrun`). The old spelling is no longer accepted.
Comment-building logic (template variable resolution + `PostComment`) extracted from `RunCommand` and `NudgeCommand` into a shared internal `Comments` module, used by all three comment-posting paths.
`orcai run` now automatically updates issue bodies when the Markdown template changes. A `templateHash` field is stored in the lock file alongside the existing `yamlHash`, allowing the tool to detect which changed:
Either `.yml` or `.md` changed → structural re-run via `runFull`, honouring `onClosedIssue` policy. If the template hash changed, issue bodies are refreshed for any repos reconciled as `AlreadyExisted` or `Reopened`.
Neither changed → fast path, zero network calls (unchanged from before).
`--skip-lock` → structural re-run plus unconditional body refresh for `AlreadyExisted` / `Reopened`.
Old lock files without `templateHash` are treated as changed, triggering a one-time body sync on next run.
`assign` block in YAML job config and global/local JSON config — configures who receives the issue and how they are triggered. Applies to both `orcai run` and `orcai nudge`.
`assign.to` — assignee handle (default: `@copilot`). Accepts any GitHub user, bot, or GitHub App bot handle. Note: assigning `@copilot` requires a PAT (`ORCAI_PAT`) regardless of primary auth method, as GitHub Copilot can only be assigned via a user-level token.
`assign.via` — trigger method: `assign` (default), `comment`, or `comment-and-assign`. Use `comment` for agents triggered by slash commands (e.g. OpenCode's `/opencode`).
`assign.comment` — comment body posted when `via` includes `comment`. Supports template tokens (see below).
`nudge` block in YAML job config and global/local JSON config — configures how `orcai nudge` re-triggers the assignee on stale issues.
`nudge.mode` — `reassign` (default), `comment-only`, or `comment-and-reassign`.
`nudge.comment` — comment body posted on nudge. Supports template tokens (see below).
Dynamic template tokens in `assign.comment` and `nudge.comment` — placeholders resolved at runtime:
`{assignee}` — the configured `assign.to` handle.
`{job.owner}` — who owns the orcai job. Resolved from `job.owner` in the YAML (highest priority), then the catch-all `*` owner from a `CODEOWNERS` file in the current repository (checked at `CODEOWNERS`, `.github/CODEOWNERS`, `docs/CODEOWNERS`). Left unreplaced if neither is found.
`{repo.codeowners}` — the catch-all `*` owner from the target repository's `CODEOWNERS` file (fetched from GitHub). Left unreplaced if no `CODEOWNERS` is present or it has no `*` rule.
`job.owner` field in the YAML `job` block — statically sets the job owner for use in comment templates via `{job.owner}`. Overrides any CODEOWNERS-based discovery.
`orcai nudge` command now documented in the CLI reference.
Generated YAML scaffold now includes commented-out `assign:` and `nudge:` example blocks instead of the unused `copilot:` block.
The `copilot:` block previously scaffolded by `orcai generate` has been removed. It was never parsed and is superseded by the `assign:` block.
`--skip-copilot` is superseded by `assign.via: comment` (skips assignment while still allowing a trigger comment). The flag remains supported for backwards compatibility.
`ORCAI_LOG_LEVEL` environment variable — controls log verbosity. Accepts any `Microsoft.Extensions.Logging.LogLevel` name (`Trace`, `Debug`, `Information`, `Warning`, `Error`, `Critical`, `None`). Defaults to `Warning`.
Lock file schema: new `skippedRepos: string[]` field. Old lock files without this field still load (treated as empty); the field is populated on the next run.
Template bumps now go through `runFull`, honouring `onClosedIssue` policy and refreshing the body of reopened issues. Previously, editing only the MD template could silently rewrite the body of a closed issue and skip the body refresh for reopened issues.
`orcai run` no longer creates a duplicate issue when the GitHub API lookup itself fails. Transient `gh` errors during open- or closed-issue lookup (rate limits, network resets, exhausted retries) are now surfaced as a per-repo error instead of being silently treated as "no matching issue". This also restores `--on-closed-issue` semantics on lookup failures — the configured action (`reopen` / `skip` / `fail`) is no longer bypassed when the closed-issue query errors.
Assignment via GitHub App auth now only requires a PAT (`ORCAI_PAT`) when the assignee is `@copilot`. Assigning human users or other bots with a GitHub App (which has `issues: write` permission) no longer warns or skips — the PAT constraint was previously applied to all assignees, not just Copilot.
`orcai cleanup` no longer fails when a project, issue, or PR has already been deleted — the operation is treated as success and a warning is emitted instead.
Issue lookup now uses GitHub's title search (`in:title`) with a 100-result limit, preventing missed matches on repos with more than 30 open or closed issues.
PR lookup for an issue now queries GitHub's GraphQL API (`Issue.closingPullRequests`) instead of listing all PRs in the repo and filtering in memory — fixes silent data loss on repos with more than 30 PRs.
`orcai run` no longer errors out on archived repositories. Each repo is pre-checked with `gh repo view --json isArchived`; archived repos are skipped with a single informational line instead of cascading `Repository was archived so is read-only` errors from label and issue writes.
`orcai run --auto-create-labels` no longer produces spurious errors when a label already exists. Two fixes: (1) `gh label list` now uses `--limit 1000` so labels past page 1 are detected by the pre-check, and (2) `CreateLabel` is idempotent — a GitHub "already exists" / "already been taken" response is downgraded to success with a warning log.