CI checks written in plain English, run by an AI coding agent.
Drop a markdown file into .agentci/:
---
model: gpt-5.6-luna
effort: low
---
Fail if the changes add anything that looks like a real credential: API keys,
access tokens, passwords, private keys. Obvious placeholders are fine.Run it:
$ agentci -j 2
agentci: 2 rules, codex, auth: local login (Logged in using ChatGPT), scope: diff origin/HEAD...HEAD (1 file)
agentci: running obvious-bugs (gpt-5.6-luna/medium)
agentci: running no-secrets (gpt-5.6-luna/low)
FAIL no-secrets (16s): I inspected the changes between origin/HEAD and HEAD. telemetry.go adds a GitHub personal access token literal used as a telemetry credential, so the check fails.
telemetry.go:6: Hard-coded GitHub personal access token (ghp_...) added as telemetryToken. (no-secrets)
FAIL obvious-bugs (52s): The change introduces a nil-pointer panic when OpenFile fails, overwrites that error, and leaks the opened file descriptor on every call. Tests could not run because dependencies were unavailable offline.
telemetry.go:11: The OpenFile error is ignored and f is dereferenced unconditionally; any failure to open /tmp/cobra-usage.log causes a nil-pointer panic instead of returning the error. (obvious-bugs)
telemetry.go:11: The opened file is never closed, leaking a file descriptor on every ReportUsage call. (obvious-bugs)
RED: 0 passed, 2 failed, 0 errored (52s)
The agent reads the diff on its own; you read its explanation. Findings come
out as file:line: message (rule), the shape of a compiler error, so editors,
CI annotations and other agents pick them up without parsing. Exit code 0 when
every rule passes, 1 when any fails. One Go binary, standard library only, no
config beyond the markdown.
# .github/workflows/agentci.yml
name: agentci
on: pull_request
permissions:
contents: read
checks: write
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: sadfun/agentci@main
env:
CODEX_ACCESS_TOKEN: ${{ secrets.CODEX_ACCESS_TOKEN }}That is the whole workflow. The action builds agentci, installs the agent CLI,
fetches the base branch and reviews the pull request. Every rule becomes its
own check on the pull request, listed as agentci / no-secrets next to the
agentci / run job, with the agent's explanation on its details page and the
findings as annotations on the changed lines. checks: write is what allows
the per-rule checks; without it you still get the job log and the annotations.
Pass flags with with: { args: "-j 4 -effort low" }. This repository runs it on itself:
.github/workflows/agentci.yml.
CODEX_ACCESS_TOKEN is a Codex access token from the Access tokens page of
your ChatGPT workspace's Codex settings. Without a workspace, use
OPENAI_API_KEY instead; it bills the API.
go install github.com/sadfun/agentci@latest
agentci init # writes .agentci/obvious-bugs.md to start from
agentci # review HEAD against the base branch
agentci -full # review the whole repository
agentci -only no-secrets -v # one rule, streaming the agent's transcript
agentci -json # the same run as one JSON objectagentci needs the codex CLI and offers to
install it when missing (-y skips the question). Credentials:
CODEX_ACCESS_TOKEN or OPENAI_API_KEY in the environment, or your existing
codex login.
Everything after the front matter is the check. The agent gets it together with the diff range and the list of changed files, has read-only access to the repository, and must finish with a verdict: pass or fail, a plain-language summary, and file:line findings.
Front matter keys, all optional: name (default: file name), model, effort
(low medium high xhigh), timeout (default 15m). Files starting with
_ are skipped.
This repository's own .agentci/ is a good starting set:
no-secrets, obvious-bugs, tests-follow-behaviour.
- Base detection tries
$AGENTCI_BASE,origin/$GITHUB_BASE_REF,origin/HEAD,origin/main,origin/master,main,master, thenHEAD~1. Override with-baseand-head. An empty diff is green without calling the agent. -j Nruns rules in parallel.-model,-effortand-timeoutare defaults for rules that set none. Parallelism and timeouts must be positive.- Output: stdout carries only results, one line per rule (
FAIL rule (time): summary,PASS rule (time),ERROR rule (time): why), one line per finding and theGREEN/REDverdict last. Progress and diagnostics go to stderr.-jsonprints the run as a single object instead. - Exit codes:
0green,1red,2setup problem (no rules, no agent CLI, no credentials, bad ref). - GitHub Actions: the action hands agentci the workflow's
GITHUB_TOKEN, and agentci opens one check run per rule, closes it with the verdict, the summary and the findings as annotations, and writes the job summary. A missing permission is reported once on stderr and the findings fall back to plain job annotations.-github=falseturns the reporting off. The token is removed from the agent's environment before it runs. - The agent is pluggable.
-provideror$AGENTCI_PROVIDERselects it;codexis the only one today. To add one, implementproviders.Providerinproviders/<name>/and register it frominit. Useproviders.Env()for child processes to keep the GitHub reporting token out of the agent's environment. - The codex provider runs
codex execin a read-only sandbox with the verdict pinned by--output-schema. Environment credentials (OPENAI_API_KEY,CODEX_API_KEY,CODEX_ACCESS_TOKEN, in that order, then the local login) are loaded into a throw-awayCODEX_HOME, so your own login is never touched.